1、awk語法:
awk [選項] '條件1{動作1} 條件2{動作2} ……' 文件名
選項:
-F:fs fs指定輸入分隔符,fs可以是字符串或正則表達式。
-v:var=value 賦值一個用戶自定義變量,將外部變量傳遞給awk。
-f:scriptfile 從腳本文件中讀取awk命令。
條件:一般使用關係表達式作爲條件。
動作:格式化輸出;流程控制語句。
2、awk的條件:
條件的類型 | 條 件 | 說 明 |
awk 保留字 | BEGIN | 在awk程序一開始時,尚未讀取任何數據之前執行。BEGIN之後的動作只在程序開始時執行一次。 |
END | 在awk程序處理完所有數據,即將結束時執行。END後的動作只在程序結束時執行一次。 | |
關係運算符 | > | 大於 |
< | 小於 | |
>= | 大於等於 | |
<= | 小於等於 | |
== | 等於。用於判斷兩個值是否相等。區別於變量賦值“=”。 | |
!= | 不等於 | |
A~B | 判斷字符串A中是否包含能匹配B表達式的子字符串 | |
A!~B | 判斷字符串A中是否不包含能匹配B表達式的子字符串 | |
正則表達式 | // | //中可以寫入字符,也支持正則表達式 |
3、BEGIN的用法:
BEGIN的執行時機是“在awk一開始,尚未讀取任何數據之前執行”。一旦BEGIN後的動作執行一次,BEGIN的條件就不再成立。
[root@master ~]# awk 'BEGIN{print "Hell World!"} {print $1"\t"$2}' /etc/hosts Hell World! 127.0.0.1 localhost ::1 localhost 192.168.1.201 master
4、END的用法:
END是在awk處理完所有數據,即將結束時執行。END的動作只在程序結束時執行一次。
[root@master ~]# awk 'END{print "The End"} {print $1"\t"$2}' /etc/hosts 127.0.0.1 localhost ::1 localhost 192.168.1.201 master The End
5、使用關係運算符:
用到的示例文件內容如下。
[root@master ~]# cat students.txt ID Name MySQL Linux Nginx Average 1 Lisan 86 95 82 87.66 2 Sunsi 96 87 74 85.66 3 Wangwu 93 99 83 91.66
想知道平均成績超過90分的學生姓名:
[root@master ~]# awk '$6>=90{print $2}' students.txt | grep -v Name Wangwu
awk命令的執行過程:
1) 如果有BEGIN條件,則先執行BEGIN定義的動作;
2) 如果沒有BEGIN條件,則讀入第一行,把第一行的數據依次賦予$0、$1、$2等變量。其中$0代表此行的整體數據,$1代表第一字段,$2代表第二字段;
3) 依據條件類型判斷動作是否執行。如果條件符合,則執行動作,否則讀入下一行數據;
4) 當所有的行匹配結束,執行END條件。
[root@master ~]# echo -e "A line 1 \nA line 2" | awk 'BEGIN{print "BEGIN"} {print} END{print "END"}' BEGIN A line 1 A line 2 END
6、使用正則表達式:
想查看學生“Wangwu”的成績:
[root@master ~]# awk '/Wangwu/{print}' students.txt 3 Wangwu 93 99 83 91.66
使用df命令查看分區使用情況時,只返回真正的系統分區的使用狀況:
[root@master ~]# df -h | awk '$1 ~ /sda[0-9]/ {print $1,$5}' /dev/sda2 20% /dev/sda1 71%
7、awk的內置變量
awk內置變量 | 作 用 |
$0 | 代表目前awk所讀入的整行數據。 |
$n | 代表目前讀入行的第n個字段(第n列)。 |
NF | 當前行擁有的字段(列)總數。 |
NR | 當前awk所處理的行,是總數據的第幾行。 |
FS | 用戶自定義分隔符。awk默認的分隔符是任何空格。 |
ARGC | 命令行參數個數 |
ARGV | 命令行參數數組 |
FNR | 當前文件中的當前記錄數 |
RS | 輸入記錄分隔符(默認爲換行符) |
ORS | 輸出記錄分隔符(默認爲換行符) |
[root@master ~]# echo -e "line1 f1 f2\nline2 f3 f4\nline3 f4 f5" | awk '{print "Line No: "NR,"No of fields: " NF,"$0: "$0, "$1: "$1,"$2: "$2,"$3: "$3 }' Line No: 1 No of fields: 3 $0: line1 f1 f2 $1: line1 $2: f1 $3: f2 Line No: 2 No of fields: 3 $0: line2 f3 f4 $1: line2 $2: f3 $3: f4 Line No: 3 No of fields: 3 $0: line3 f4 f5 $1: line3 $2: f4 $3: f5
使用分隔符:
[root@master ~]# cat /etc/passwd | awk -F ':' '{printf $1"\t"$3"\n"}' 或 [root@master ~]# cat /etc/passwd | awk 'BEGIN{FS=":"} {printf $1"\t"$3"\n"}'
8、awk流程控制:
求學生的MySQL成績的總和:
[root@master ~]# awk 'NR==2{s1=$3} NR==3{s2=$3} NR==4{s3=$3;total=s1+s2+s3;print "Total is:" total}' students.txt Total is:275 或者 [root@master ~]# awk 'NR>1{s+=$3}END{print "Total is:" s}' students.txt Total is:275
注意區分:
[root@master ~]# awk 'NR==2{s1=$3} NR==3{s2=$3} NR==4{s3=$3} {total=s1+s2+s3;print "Total is:" total}' students.txt Total is:0 Total is:86 Total is:182 Total is:275
如果MySQL成績大於90,則輸出“is a good student!”:
[root@master ~]# awk '{if(NR>=2 && NR<=4){if($3>90){print $2,"is a good student!"}}}' students.txt Sunsi is a good student! Wangwu is a good student! 或者 [root@master ~]# awk 'NR>=2 && NR<=4 && $3>90{print $2,"is a good student!"}' students.txt Sunsi is a good student! Wangwu is a good student!
第一個if條件,判斷行數在2(包含)到4(包含)之間;
第二個if條件,判斷第三列(即MySQL列)是否大於90;
print語句中的“,”會在標準輸出中輸入一個空格。
注意事項:
多個“條件{動作}”可以用空格分隔,也可以用回車分隔;
在一個動作中,如果需要執行多個命令,需要用“;”分隔,或者用回車分隔;
在awk中,變量的賦值和調用都不需要加入“$”;
條件判斷中如果判斷兩個值是否相同,使用"==";
當使用不帶參數的print時,它就打印當前行的內容。當print的參數是以逗號做分隔符時,打印的結果以空格作爲定界符;
在awk的print語句塊中雙引號是被當作拼接符使用;
在進行算術運算時,所有操作數自動轉爲數值,所有非數值都變爲0。
[root@master ~]# echo | awk 'a="b" {print a++, ++a}' 0 2
9、awk函數
定義方法如下:
function 函數名(參數列表){ 函數體 }
實例,在第二列和第三列中間加“ ||| ”:
[root@master ~]# awk 'function test(a,b){print a,"|||",b} test($2, $3)' students.txt Name ||| MySQL Lisan ||| 86 Sunsi ||| 96 Wangwu ||| 93
10、awk中調用腳本
創建一個.awk結尾的文件:
[root@master ~]# cat pass.awk BEGIN{print "Hello Boys"} {print $1,$2,$3} END{print "Bye Boys"}
通過-f選項調用:
[root@master ~]# awk -f pass.awk students.txt Hello Boys ID Name MySQL 1 Lisan 86 2 Sunsi 96 3 Wangwu 93 Bye Boys
11、用awk按列求和:
用到的示例文件內容如下:
[root@master ~]# cat file1 a 1 a 3 a 4 c 6
求第二列的和:
[root@master ~]# awk '{s+=$2}END{print s}' file1 14
12、用awk進行分組求和:
用到的示例文件內容如下:
[root@master ~]# cat file2 a 1 2 a 2 3 a 2 5 c 4 6
以第一列爲變量名,將相同第一列的第二列數據進行累加,打印出和:
[root@master ~]# awk '{s[$1]+=$2} END{for(i in s){print i,s[i]}}' file2 a 5 c 4
以第一列、第二列爲變量名,將相同第一列、第二列的第三列的數據進行累加,打印出和:
[root@master ~]# awk '{s[$1,$2]+=$3} END{for(i in s){print i,s[i]}}' file2 c4 6 a1 2 a2 8
以第一列爲變量名,打印出第二列和第三列的數據和:
[root@master ~]# awk '{s[$1]+=$2; a[$1]+=$3} END{for(i in s){print i,s[i],a[i]}}' file2 a 5 10 c 4 6
13、將外部變量傳遞給awk:
指定-v參數,可以將環境變量傳遞給awk使用:
[root@master ~]# var=100 [root@master ~]# echo | awk -v VARIABLE=$var '{print VARIABLE}' 100
14、awk高級輸入輸出
awk中next語句使用:逐行匹配,如果遇到next,就會跳過當前行,進行下一次匹配。next語句一般用於合併多行:
[root@master ~]# awk '$2~/Name/{T=$2;next}{print T"\t"$2}' students.txt Name Lisan Name Sunsi Name Wangwu