awk用法

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





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章