一、AWK概念
awk 是一種編程語言,用於在linux/unix下對文本和數據進行處理。數據可以來自標準輸(stdin)、一個或多個文件,或其它命令的輸出。它在命令行中使用,但更多是作爲腳本來使用。awk有很多內建的功能,比如數組、函數等,這是它和C語言的相同之處,靈活性是awk最大的優勢。
二、AWK用法
1、語法格式
awk [options] 'scripts' var=value file(s)
awk [options] -f scriptfile var=value file(s)
2、常用參數
-F 指定分隔符(可以是字符串或正則表達式;如-F:)
-f 從腳本文件中讀取awk命令
-v var=value 賦值變量,將外部變量傳遞給awk
3、內置變量
ARGC 命令行參數個數
ARGV 命令行參數排列
ENVIRON 支持隊列中系統環境變量的使用
FILENAME awk瀏覽的文件名
FNR 瀏覽文件的記錄數
FS 設置輸入域分隔符,等價於命令行 -F選項
NF 瀏覽記錄的域的個數,執行過程中對應於當前的字段數
NR 已讀的記錄數,相當於行號
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
$0變量是指整條記錄。$1表示當前行的第一個域,$2表示當前行的第二個域,......以此類推。
$NF是number finally,表示最後一列的信息,跟變量NF是有區別的,變量NF統計的是每行列的總數
4、常用參數
-F 指定分隔符(可以是字符串或正則表達式)
-f 從腳本文件中讀取awk命令
-v var=value 賦值變量,將外部變量傳遞給awk
5、AWK模式和操作
模式
/正則表達式/:使用通配符的擴展集
關係表達式:使用運算符進行操作,可以是字符串或數字的比較測試
模式匹配表達式:用運算符~(匹配)和!~(不匹配)
BEGIN語句塊、pattern語句塊、END語句塊
操作
操作是由一個或多個命令、函數、表達式組成,之間由換行符或分號隔開,並位於大括號內,主要部分是:變量或數組賦值、輸出命令、內置函數、控制流語句
6、AWK腳本基本結構
awk 'BEGIN{ print "start" } pattern{ commads } END{ print "end" }' file
三、awk工作原理
awk 'BEGIN{ commads } pattern{ commads } END{ commads }'
第一步:執行BEGIN{ commads }語句塊的語句
第二步:從文件或標準輸入(stdin)讀取一行,然後執行pattern{ commads }語句塊,它逐步掃描文件,從第一行到最後一行重複這個過程,直到文件全部被讀取完畢
第三步:當讀至輸入流末尾時,執行END{ commads }語句塊
BEGIN{ commads }語句塊 在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通常可以寫在BEGIN語句塊
END{ commads }語句塊 在awk從輸入流中讀取完所有的行之後即被執行,它也是一個可選語句塊
pattern{ commads }語句塊 中的通用命令是最重要的部分,它也是可選的。如果沒有提供pattern語句塊,則默認執行{ print },即打印讀取到的每一行,awk讀取的每一行都會執行該語句塊
示例
[root@os test]# awk '/root/' /etc/passwd #默認是打印讀取到的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@os test]# awk -F: '/root/ { print $1,$NF }' /etc/passwd #以:分隔,打印第一和最後一列
root /bin/bash
operator /sbin/nologin
[root@os test]# echo -e "a line \nb line" | awk 'BEGIN{ print "start" } { print } END{ print "end" }'
start
a line
b line
end
#統計/etc/passwd文件中每行的字符數
[root@os test]# awk -F "" '{for(i=1;i<=NF;i++) if($i!="\n") ++sum;print sum;a=a+sum;sum=0}END{print "sum:"a}' /etc/passwd
四、外部變量、運算、判斷
1、外部變量,藉助 -v選項,可以將外部值傳遞給awk
[root@os test]# var=10010
[root@os test]# echo | awk -v VARIABLE=$var '{ print VARIABLE }'
10010
[root@os test]# unset var #撤消變量
2、運算
類型 | 運算符 | 描述 |
---|---|---|
算術運算符 | + - | 加,減 |
* / & | 乘,除,求餘 | |
+ - ! | 一元加,減和邏輯非 | |
^*** | 求冪 | |
++ -- | 增加或減少,作爲前綴或後綴 | |
賦值運算符 | =、+=、-=、/=、%=、^=、**= | 例:a+=5,等價於a=a+5,其它類同 |
邏輯運算符 | ||、&& | 邏輯或和邏輯與 |
關係運算符 | <、<=、>、>=、!=、== | |
正則運算符 | ~、!~ | 匹配正則和不匹配正則 |
其它運算符 | ? | 條件表達式 |
$ | 字段引用 | |
in | 數組中是否存在某鍵值 |
算術運算示例
[root@os test]# awk 'BEGIN{ a="b";print a++,++a}'
0 2
#注意:所有用作算術運算符進行操作,操作數自動轉爲數值,所有非操作數值變爲0
賦值運算示例
[root@os test]# awk 'BEGIN{ a=4;print a+=5}'
9
[root@os test]# awk 'BEGIN{ a=4;print a*=5}'
20
邏輯運算示例
[root@os test]# awk 'BEGIN{ a=4;b=3;print (a>5 && b<4),(a>5 || b<4)}'
0 1
關係運算示例
[root@os test]# awk 'BEGIN{ a=4;if(a<5){print "ok"}}'
ok
正則運算示例
[root@os test]# awk 'BEGIN{ a="100absfc";if(a ~ /^100/){print "ok"}}'
其它運算示例
[root@os test]# awk 'BEGIN{ a="b";arr[0]="b";arr[1]="c";print (a in arr)}'
0
[root@os test]# awk 'BEGIN{ a="b";arr[0]="b";arr["b"]="c";print (a in arr)}'
1
[root@os test]# awk 'BEGIN{ a=10;print a<9?"ok":"err"}'
err
五、AWK高級輸入輸出
1、讀取下一條記錄
awk中next語句使用:在循環逐行匹配,如果遇到next,就會跳過當前行,直接忽略下面語句而進行下一行匹配。多用於多行合併
[root@os awktest]# vi test.txt
a
b
c
d
e
[root@os awktest]# awk 'NR%2==1{next}{print NR,$0}' test.txt
2 b
4 d
[root@os awktest]# vi next.txt
httpd ok
web01[192.168.1.101]
httpd ok
tomcat ok
sendmail ok
web02[192.168.1.102]
httpd ok
postfix ok
web03[192.168.1.103]
httpd ok
mysqld ok
[root@os awktest]# awk '/^web/{T=$0;next}{print T":\t"$0;}' next.txt
web01[192.168.1.101]: httpd ok
web01[192.168.1.101]: tomcat ok
web01[192.168.1.101]: sendmail ok
web02[192.168.1.102]: httpd ok
web02[192.168.1.102]: postfix ok
web03[192.168.1.103]: httpd ok
web03[192.168.1.103]: mysqld ok
2、讀取一條記錄
awk getline:輸出重定向需要使用getline函數。getline從標準輸入、管道或者當前正在處理的文件之外的其它輸入文件獲得輸入。它負責從輸入獲得下一行內容,並給NF,NR,FNR等內置變量賦值。
用法說明:
當其左在右無重寫向符|或<時,getline作用於當前文件,讀入當前文件的第一行給其後綴的變量var或$0,應該注意到,由於awk在處理getline之前已經讀入一行,所以getline得到的返回結果是隔行的
當其左在右有重寫向符|或<時,geline則作用於定向輸入文件,由於該文件是剛打開,並沒有被awk讀入一行,只是getline讀入,那麼getline返回的是該文件的第一行,而不是隔行
[root@os awktest]# awk 'BEGIN{ "date" | getline out; print out }' test
Sat Mar 14 12:06:53 EDT 2020
[root@os awktest]# awk '{ getline } /root/ ' /etc/passwd
operator:x:11:0:operator:/root:/sbin/nologin #注意,這裏是隔行的,所以只匹配到一個
六、流程控制語句
在linux awk的while、do-while和for語句中允許使用break,continue語句來控制流程走向,也允許exit語句退出。awk中,流程控制語句,語法結構,與C語言類似。有了這些,很多shell程序都可以交給awk,而且性能非常快
#if語句
[root@os awktest]# awk ' BEGIN{test=100;if(test>90){print "very good"}else if(test>60){print "good"}else{prit "no pass"}}'
very good
#while語句
[root@os awktest]# awk 'BEGIN{test=13;total=0;while(i<=test){total+=i;i++}print total}'
91
#for語句(2種格式)
[root@os awktest]# awk 'BEGIN{for(k in ENVIRON){print k"="ENVIRON[k];}}'
AWKPATH=.:/usr/share/awk
OLDPWD=/root
SELINUX_LEVEL_REQUESTED=
SELINUX_ROLE_REQUESTED=
......
36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
[root@os awktest]# awk 'BEGIN{for(i=0;i<=13;i++){total+=i}print total;}'
91
七、數組應用
1、數組的定義
數字幫數組索引(下標):
array[1]="sun"
array[2]="shitou"
字符串做數組索引(下標):
array["first"]="www"
array["last"]="name"
array["birth"]="1990"
[root@os awktest]# awk 'BEGIN{array[1]="sun";array[2]="shitou";array["first"]="www";array["last"]="name";array["birth"]="1990"; { print array[1] "\n" array["first"]}}'
sun
www
[root@os awktest]# awk 'BEGIN{array[1]="sun";array[2]="shitou";array["first"]="www";array["last"]="name";array["birth"]="1990"; { for(item in array){print array[item]}}}'
1990
www
name
sun
shitou
[root@os awktest]# awk 'BEGIN{array[1]="sun";array[2]="shitou";array["first"]="www";array["last"]="name";array["birth"]="1990"; { for(i=1;i<=2;i++){print array[i]};} }'
sun
shitou
2、數組相關函數
#輸出數組長度
[root@os awktest]# awk 'BEGIN{info="it is a test";lens=split(info,tA," ");print length(tA), lens;}'
4 4
#length返回字符串以及數組長度,split進行分割字符串爲數組,也會返回分割得到的數組長度