awk生於1977年,創始人有三個,分別為 Alfred Aho,Peter Weinberger, 和 Brian Kernighan,名稱源於三個創始人的姓的首字母。
作用:處理文本文件。
awk的特色是可以對行和列進行操作,輸入man awk可以查看awk手冊,下面將主要以例子來學習awk語言。
語法:
mawk [-W option] [-F value] [-v var=value] [--] 'program text' [file ...] mawk [-W option] [-F value] [-v var=value] [-f program-file] [--] [file ...]
參數-實例:
1、初識awk
截取top命令部分內容,拷貝到test.txt里:
amosli@amosli-pc:~/learn/awk$ cat test.txt 1067 root 20 0 200m 49m 11m S 2 1.3 4:43.91 Xorg 3009 amosli 20 0 534m 21m 12m S 1 0.5 0:14.75 gnome-terminal 1002 mongodb 20 0 623m 15m 4728 S 1 0.4 0:41.17 mongod 2412 amosli 20 0 1005m 125m 17m S 1 3.2 0:48.61 chrome 3775 root 20 0 0 0 0 S 1 0.0 0:00.98 kworker/0:0 3829 amosli 20 0 17344 1356 952 R 1 0.0 0:00.11 top 2102 amosli 20 0 686m 8280 3508 S 0 0.2 0:10.11 hud-service 2176 amosli 20 0 419m 10m 8448 S 0 0.3 0:00.11 telepathy-indic 3621 root 20 0 0 0 0 S 0 0.0 0:03.30 kworker/1:2 1 root 20 0 24580 2524 1336 S 0 0.1 0:00.70 init 2 root 20 0 0 0 0 S 0 0.0 0:00.00 kthreadd 3 root 20 0 0 0 0 S 0 0.0 0:00.92 ksoftirqd/0 6 root RT 0 0 0 0 S 0 0.0 0:01.13 migration/0 7 root RT 0 0 0 0 S 0 0.0 0:00.14 watchdog/0 8 root RT 0 0 0 0 S 0 0.0 0:02.16 migration/0
下面打印第2列的內容,注意pattern里是單引號.
amosli@amosli-pc:~/learn/awk$ awk '{print $2}' test.txt root amosli mongodb amosli root amosli amosli amosli root root root root root root root
$0表示打印出來全部,$n,n>0時表示打印第n列。
2、拆解awk語句塊
先看例子:
amosli@amosli-pc:~/learn/awk$ awk 'BEGIN { i=0 } {i++} END { print i } ' test.txt 15
ok,是不是用點不太懂?看不太懂沒關系,下面拆解開來,一個awk腳本通常分為3部分:BEGIN 語句塊、END語句塊和能夠使用模式匹配的通用語句塊。這三個部分是可選的,它們中的任何一個部分都可以不出現在腳本中。腳本通常包含在單引號或者雙引號里。其通用模式結構如下所示:
awk ' BEGIN { print "start" } pattern { commands } END { print "end" }' file
下面是實際常用的語法格式:
awk 'BEGIN { statements } { statements } END { end statements }' filename
awk的工作原理:
(1)、執行BEGIN { commands }語句塊中的語句。
(2)、從文件或stdin中讀取一行,然后執行pattern { commands }。重復這個過程,直到文件全部被讀取完畢。
(3)、當讀至輸入流(input stream)末尾時,執行END { commands } 語句塊。
BEGIN語句塊在awk開始從輸入流中讀取行之前被執行。這是一個可選的語句塊。
END語句塊在awk從輸入流中讀取完所有的行之后即被執行。這個同樣是可選的。
最重要的部分就是pattern語句塊中的通用命令。這個同樣是可選的。如果不提供該語句塊,則默認執行的是{ print },即打印每一個讀取到的行。awk對於讀取到的每一行,都會執行這個語句塊.例:
amosli@amosli-pc:~/learn/awk$ echo -e "line1\nline2" | awk 'BEGIN { print "now start" } { print } END { print "this is end" } ' now start line1 line2 this is end
這里首先執行的是BEGIN { print "now start" },然后開始執行默認打印line1\nline2 ,最后讀完所有的行之后開始執行END語句塊{ print "this is end "}
同樣可以將BEGIN和END都去掉,只使用默認的打印方式:
amosli@amosli-pc:~/learn/awk$ echo -e "line1\nline2" | awk '{ print }' line1 line2
這種方式和例1的方式則是相同的。學完這兩個例子,基本上就明白了awk到底咋用的了,其格式應該是什么樣,即已經入門了。
3、關於print
這里的print和C語言中的基本上差別不大,但C語言我早已經忘的差不多了。還是來看看awk里的print是怎么使用的吧?
有兩點需要注意:
1、當print的參數是以逗號進行分隔時,參數打印時則以空格作為定界符。
2、在awk 的print語句中,雙引號是被當做拼接操作符的(concatenation operator) ,所以模式匹配最外層盡量使用單引號.
關於1,舉例說明:
amosli@amosli-pc:~/learn/awk$ echo | awk ' { var1="v1";var2="v2"; print var1,var2 } ' v1 v2
這里print var1,var2用的是逗號進行分隔的,所以打印時是以空格作為定界符的。那如果不以逗號進行分隔呢?
amosli@amosli-pc:~/learn/awk$ echo | awk ' { var1="v1";var2="v2"; print var1 var2 } ' v1v2
打印的時候v1v2貼到一塊去了。如果再用其它符號進行分隔,打印會出錯(我試了| : \ /)。
關於2,舉例說明:
amosli@amosli-pc:~/learn/awk$ echo | awk ' { var1="v1";var2="v2"; print var1"+" var2 } ' v1+v2
這里使用了"+",雙引號果然起到了連接的作用。
4、特殊變量
NR:表示記錄數量(number of records),表示當前行號,和cat命令中-n 意思一樣。
NF:表示字段數量(number of fields),表示當前行的字段數量
$0,$1,$2,$n.... 前面已經說過,$0表示輸出所有文本內容,$n表示第n行數據。
舉例說明NR和NF:
下面是NF
amosli@amosli-pc:~/learn/awk$ cat test.txt | awk '{ print NF }' 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12
每一行都有12個字段,"1067 root 20 0 200m 49m 11m S 2 1.3 4:43.91 Xorg",這里字段的定義不是字母數量,而是由空格隔開產生的一列為一個字段,
也可以理解為列數;
下面是NR:
amosli@amosli-pc:~/learn/awk$ cat test.txt | awk '{ print NR }' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
一共有15行。
5、將外部變量值傳遞給awk,-v參數
amosli@amosli-pc:~/learn/awk$ var=99; amosli@amosli-pc:~/learn/awk$ echo | awk -v vr=$var '{ print vr }' 99
首先,定義一個var變量,賦值99;然后,將var變量的值在外部再賦給vr;最后打印出vr。
其實就是借值傳值。但是當要傳遞很多參數時就蛋疼了,太麻煩了。下面介紹一個相對簡便的方法進行外部傳值。
amosli@amosli-pc:~/learn/awk$ echo | awk '{ print y1,y2 }' y1=$v1 y2=$v2 1 2
這里沒有使用-v參數,只是將y1=$v1傳值放到后面去了,其實就是將y1=$v1 y2=$v2 當成file了 類似 awk '{print }' file。
6、使用awk進行過濾
1)只顯示前四行,行數小於5,和head test.txt -n 4 效果一樣。
amosli@amosli-pc:~/learn/awk$ awk 'NR<5' test.txt 1067 root 20 0 200m 49m 11m S 2 1.3 4:43.91 Xorg 3009 amosli 20 0 534m 21m 12m S 1 0.5 0:14.75 gnome-terminal 1002 mongodb 20 0 623m 15m 4728 S 1 0.4 0:41.17 mongod 2412 amosli 20 0 1005m 125m 17m S 1 3.2 0:48.61 chrome
2)只顯示3-5行內容.
amosli@amosli-pc:~/learn/awk$ awk 'NR==3,NR==5' test.txt 1002 mongodb 20 0 623m 15m 4728 S 1 0.4 0:41.17 mongod 2412 amosli 20 0 1005m 125m 17m S 1 3.2 0:48.61 chrome 3775 root 20 0 0 0 0 S 1 0.0 0:00.98 kworker/0:0
3)只顯示包含amos的行
amosli@amosli-pc:~/learn/awk$ awk '/amos/' test.txt 3009 amosli 20 0 534m 21m 12m S 1 0.5 0:14.75 gnome-terminal 2412 amosli 20 0 1005m 125m 17m S 1 3.2 0:48.61 chrome 3829 amosli 20 0 17344 1356 952 R 1 0.0 0:00.11 top 2102 amosli 20 0 686m 8280 3508 S 0 0.2 0:10.11 hud-service 2176 amosli 20 0 419m 10m 8448 S 0 0.3 0:00.11 telepathy-indic
7、awk的內建函數
toupper(string),將字符串轉為大寫
amosli@amosli-pc:~/learn/awk$ awk ' { print toupper("yes") }' YES
length,長度
amosli@amosli-pc:~/learn/awk$ awk ' { print length }' test.txt 80 80 80 80 80 80 80 80 80 80 80 80 80 80 72
sqrt()取平方根
amosli@amosli-pc:~/learn/awk$ awk '{ print sqrt(4)}' 2
awk的功能非常強大,知識點也非常多,網上資料也非常多,這里主要學習的是linux shell腳本攻略第1版內容,awk的內容還需要更進一步的學習!
總結下: 這將是近半個月來linux學習的最后一篇文章了,shell腳本入門容易,但是,學過就忘,抽空一定要將這20篇內容再回顧一遍。shell功能非常強大,主要在於命令太多,靈活性較高,每個命令都有很多地方去深究。想要真正掌握所學命令那就是反復的用,不用,學了也沒意義了。我的編程最大的心得就是實踐,動手實踐,人都是眼高手低,一定要多動手!
awk進一步學習參考資料:
1、awk學習筆記
2、awk英文文檔
3、awk簡明教程