gawk程序的简单使用
一、gawk程序的基本格式
gawk options program file(1)常用的選項如下:
-F fs 指定行中劃分數(shù)據(jù)字段的字段分隔符 -f file 從指定文件中讀取程序 -v var=value 定義gawk程序中的一個變量及其默認值 -mf N 指定要處理的數(shù)據(jù)文件中的最大字段數(shù) -mr N 指定數(shù)據(jù)文件中的最大數(shù)據(jù)行數(shù) -W keyword 指定gawk的兼容模式或警告等級(2)使用的數(shù)據(jù)字段變量
默認情況下,gawk會將如下變量分配給它在文本行中發(fā)現(xiàn)的數(shù)據(jù)字段:
$0 代表整個文本行 $1 代表文本行中的第一個數(shù)據(jù)字段 $2 代表文本行中的第二個數(shù)據(jù)字段 $n 代表文本行中的第n個數(shù)據(jù)字段在文本行中,每個數(shù)據(jù)字段是通過字段分隔符劃分的,gawk默認的字段分隔符是任意的空白字符,例如空格或制表符。
(3)在程序腳本中使用多個命令
gawk程序允許將多條命令組合成一個正常的程序,命令之間是用分號即可。
echo "my name is bob"|gawk '{$4="jack" ; print $0}'[root@test ~]# echo "my name is bob"|gawk '{$4="jack" ; print $0}' my name is jackgawk程序中的第一條命令會給字段變量$4賦值,第二條命令打印整個數(shù)據(jù)字段。
(4)從文件中讀取程序
gawk編輯器允許將程序存儲到文件中,然后再在命令行中引用。
cat script.gawk {print $1 "'s home directory is " $6}gawk -F ':' -f script.gawk /etc/passwd[root@test ~]# gawk -F ':' -f script.gawk /etc/passwd root's home directory is /root bin's home directory is /bin daemon's home directory is /sbin可以在程序文件中指定多條命令,只要每條命令放一行即可,不需要用分號。
cat script.gawk { text="'s home directory is " print $1 text $6 }gawk -F ':' -f script.gawk /etc/passwd[root@test ~]# gawk -F ':' -f script.gawk /etc/passwd root's home directory is /root bin's home directory is /bin daemon's home directory is /sbin可以看到gawk程序在引用變量值時并未像shell腳本一樣使用美元符。
(5)在處理數(shù)據(jù)前運行腳本
gawk在讀取數(shù)據(jù)前會執(zhí)行BEGIN關(guān)鍵字后指定的程序腳本。
gawk 'BEGIN {print "hello word!"}'[root@test ~]# gawk 'BEGIN {print "hello word!"}' hello word!可以看到print命令會在讀取數(shù)據(jù)前顯示文本,但是在它顯示了文本后,會快速退出,不等待任何數(shù)據(jù)。如果想使用正常的程序腳本處理數(shù)據(jù),必須使用另一個腳本區(qū)域來定義程序。
cat data.txt line 1 line 2 line 3gawk 'BEGIN {print "the data file content:"} {print $0}' data.txt[root@test ~]# gawk 'BEGIN {print "the data file content:"} {print $0}' data.txt the data file content: line 1 line 2 line 3(6)在處理數(shù)據(jù)后運行腳本
與BEGIN類似,END關(guān)鍵字允許指定一個程序腳本,gawk會在讀完數(shù)據(jù)后執(zhí)行它。
gawk 'BEGIN {print "the data file content:"} {print $0} END {print "end of file"} ' data.txt[root@test ~]# gawk 'BEGIN {print "the data file content:"} {print $0} END {print "end of file"} ' data.txt the data file content: line 1 line 2 line 3 end of file(7)綜合小案例
cat script.gawk BEGIN { print "the latest list of users and shells" print " UserID \t Shell" print "------ \t -------" FS=":" }{ print $1 " \t " $7 }END { print "this concludes ths listing" }gawk -f script.gawk /etc/passwd[root@test ~]# gawk -f script.gawk /etc/passwd the latest list of users and shellsUserID Shell ------ ------- root /bin/bash bin /sbin/nologin daemon /sbin/nologin this concludes ths listing二、gawk程序的進階使用
(1)使用變量,gawk支持內(nèi)建變量和自定義變量的使用。
內(nèi)建變量:
| 變量 | 描述 |
| FIELDWIDTHS | 由空格分隔的一列數(shù)字,定義了每個數(shù)據(jù)字段確切寬度 |
| FS | 輸入字段分隔符 |
| RS | 輸入記錄分隔符 |
| OFS | 輸出字段分隔符 |
| ORS | 輸出記錄分隔符 |
變量FS和OFS定義了gawk如何處理數(shù)據(jù)流中的數(shù)據(jù)字段。變量OFS具備同樣的功能,只不過是用在print命令的輸出上。
默認情況下,OFS設(shè)成一個空格,所以在使用命令:print $1,$2,$3會看到如下的輸出結(jié)果
cat data.txt data11,data12,data13 data21,data22,data23 data31,data32,data33[root@test ~]# gawk 'BEGIN {FS=","} {print $1,$2,$3}' data.txt data11 data12 data13 data21 data22 data23 data31 data32 data33print命令會自動將OFS變量的值放置在輸出中的每個字段之間,通過設(shè)置OFS變量,可以在輸出中使用任意字符串來分隔字段。
[root@~]# cat data.txt data11,data12,data13 data21,data22,data23 data31,data32,data33[root@~]# gawk 'BEGIN {FS=",";OFS="-"} {print $1,$2,$3}' data.txt data11-data12-data13 data21-data22-data23 data31-data32-data33[root@~]# gawk 'BEGIN {FS=",";OFS="<->"} {print $1,$2,$3}' data.txt data11<->data12<->data13 data21<->data22<->data23 data31<->data32<->data33FIELDWIDTHS變量允許你不依靠字段分隔符來讀取記錄,在一些應用程序中,數(shù)據(jù)并沒有使用字段分隔符,而是被放置在了記錄中的特定列,這種情況下,必須設(shè)置FIELDWIDTHS變量來匹配數(shù)據(jù)在記錄中的位置。一旦設(shè)置了FIELDWIDTHS變量,gawk就會忽略FS變量,并根據(jù)提供的字段寬度來計算字段。
cat data1.txt 1005.3243545.34 117-2.456456.03 06458.3473749.1[root@~]# gawk 'BEGIN {FIELDWIDTHS="3 5 2 5"} {print $1,$2,$3,$4}' data1.txt 100 5.324 35 45.34 117 -2.45 64 56.03 064 58.34 73 749.1可以看到上面的例子中使用變量FIELDWIDTHS變量定義了4個字段,gawk依此來解析數(shù)據(jù)記錄,每個記錄中的數(shù)字串會根據(jù)以定義好的字段長度來分割。
變量RS和ORS定義了gawk程序如何處理數(shù)據(jù)流中的記錄,默認情況下,gawk程序?qū)S和ORS設(shè)置為換行符。默認的RS值表明,輸入數(shù)據(jù)流中的每行新文本就是一條新紀錄。
cat data2.txt riley mullen 123 main street chicago,IL 38383 (312)555-1234frank will 456 oak street indianapolis,in 345 (317)555-9876gawk 'BEGIN {FS="\n";RS=""} {print $1,$4}' data2.txt[root@test~]# gawk 'BEGIN {FS="\n";RS=""} {print $1,$4}' data2.txt riley mullen (312)555-1234 frank will (317)555-9876從上例中可以看到gawk程序把文件中的每行當作一個字段,把空白行當作記錄分隔符。
除了字段和記錄分隔符變量外,gawk還提供了其他的內(nèi)建變量如下所示:(列舉了幾個常用的)
NF 數(shù)據(jù)文件中的字段總數(shù) NR 已處理的輸入記錄數(shù) FNR 當前數(shù)據(jù)文件中的數(shù)據(jù)行數(shù)當要在gawk程序中跟蹤數(shù)據(jù)字段和記錄時,變量FNR、NR和NF用著就會很方便。NF變量可以讓你在不知道具體位置的情況下就可以指定記錄中的最后一個數(shù)據(jù)字段。
gawk 'BEGIN{FS=":";OFS=":"} {print $1,$NF}' /etc/passwd[root@test~]# gawk 'BEGIN{FS=":";OFS=":"} {print $1,$NF}' /etc/passwd root:/bin/bash bin:/sbin/nologin [root@test]# cat data.txt data11,data12,data13 data21,data22,data23 data31,data32,data33gawk 'BEGIN {FS=","} {print $1,"FNR="FNR,"NR="NR} END {print "there where",NR,"records processed"}' data.txt[root@test]# gawk 'BEGIN {FS=","} {print $1,"FNR="FNR,"NR="NR} END {print "there where",NR,"records processed"}' data.txt data11 FNR=1 NR=1 data21 FNR=2 NR=2 data31 FNR=3 NR=3 there where 3 records processedgawk 'BEGIN {FS=","} {print $1,"FNR="FNR,"NR="NR} END {print "there where",NR,"records processed"}' data.txt data.txt[root@test]# gawk 'BEGIN {FS=","} {print $1,"FNR="FNR,"NR="NR} END {print "there where",NR,"records processed"}' data.txt data.txt data11 FNR=1 NR=1 data21 FNR=2 NR=2 data31 FNR=3 NR=3 data11 FNR=1 NR=4 data21 FNR=2 NR=5 data31 FNR=3 NR=6 there where 6 records processed從結(jié)果可以看到,FNR變量的值在gawk處理第二個文件時被重置了,但是NR變量則在處理第二個文件時繼續(xù)計數(shù)。
結(jié)果就是,如果只使用第一個文件作為輸入,FNR和NR的值相同,如果使用多個文件作為輸入,FNR的值只會在處理
每個文件時被重置,NR的值則會繼續(xù)計數(shù)直到處理完所有的數(shù)據(jù)文件。
自定義變量:
gawk自定義變量名可以是任意數(shù)目的字母,下劃線和數(shù)字,但不能以數(shù)字開頭。重要的是,要記住gawk變量名區(qū)分大小寫。
- 在腳本中給變量賦值
gawk變量可以保存數(shù)值或文本值。
gawk 'BEGIN{test="this is a test";print test}'[root@test]# gawk 'BEGIN{text="this is a test";print text}' this is a test[root@test]# gawk 'BEGIN{text="this is a test";print text;text=100;print text}' this is a test 100賦值語句還可以包含數(shù)學算式來處理數(shù)字值。
gawk 'BEGIN{x=4;x=x+4;print x}'[root@test]# gawk 'BEGIN{x=4;x=x+4;print x}' 8- 在命令行上給變量賦值
但是使用命令行參數(shù)定義變量值會有一個問題,就是設(shè)置了變量后,這個值在代碼的BEGIN部分不可用。
[root@test]# cat data.txt data11,data12,data13 data21,data22,data23 data31,data32,data33cat script BEGIN {print "the starting value is",n;FS=","} {print $n}gawk -f script n=2 data.txt[root@test]# gawk -f script n=2 data.txt the starting value is data12 data22 data32可以使用-v參數(shù)來解決這個問題,-v參數(shù)允許在BEGIN代碼之前設(shè)定變量。在命令行上,-v命令參數(shù)必須放在腳本代碼之前。
[root@test]# cat data.txt data11,data12,data13 data21,data22,data23 data31,data32,data33cat script BEGIN {print "the starting value is",n;FS=","} {print $n}gawk -v n=2 -f script data.txt[root@test]# gawk -v n=2 -f script data.txt the starting value is 2 data12 data22 data32(2)使用模式
- 正則表達式
在使用正則表達式時,正則表達式必須出現(xiàn)在它要控制的程序腳本的左花括號前。
gawk 'BEGIN {FS=","} /11/{print $1}' data.txt [root@test]# gawk 'BEGIN {FS=","} /11/{print $1}' data.txt data11正則表達式/11/匹配了數(shù)據(jù)字段中含有字符串11的記錄,gawk程序會用正則表達式對記錄中所有的數(shù)據(jù)字段進行匹配,包括字段分隔符。
- 匹配操作符
匹配操作符允許將正則表達式限定在記錄中的特定數(shù)據(jù)字段,匹配操作符是波浪線~??梢灾付ㄆヅ洳僮鞣?、數(shù)據(jù)字段變量以及要匹配的正則表達式。
[root@test]# gawk 'BEGIN {FS=","} $2 ~ /^data2/{print $0}' data.txt data21,data22,data23匹配操作符會用正則表達式/^data2/來比較第二個數(shù)據(jù)字段,該正則表達式指明字符串要以文本data2開頭。
gawk -F ':' '$1 ~ /root/{print $1,$NF}' /etc/passwd[root@test]# gawk -F ':' '$1 ~ /root/{print $1,$NF}' /etc/passwd root /bin/bash這個例子會在第一個字段中查找文本root,如果在記錄中找到了這個模式,他會打印該記錄的第一個數(shù)據(jù)字段和最后一個數(shù)據(jù)字段值。
也可以使用!排除正則表達式的匹配。
gawk -F ':' '$1 !~ /root/{print $1,$NF}' /etc/passwd[root@test]# gawk -F ':' '$1 !~ /root/{print $1,$NF}' /etc/passwd bin /sbin/nologin daemon /sbin/nologin adm /sbin/nologin lp /sbin/nologin sync /bin/sync shutdown /sbin/shutdown halt /sbin/halt- 數(shù)學表達式
可以在匹配模式中使用數(shù)學表達式,可以使用任何常見的數(shù)學表達式。
x==y x<=y x<y x>=y x>y顯示所有屬于root用戶組(組ID=0)的系統(tǒng)用戶:
gawk -F ':' '$4 == 0 {print $1}' /etc/passwd[root@test]# gawk -F ':' '$4 == 0 {print $1}' /etc/passwd root sync shutdown halt operator sys_admin也可以對文本數(shù)據(jù)使用表達式,但必須小心,跟正則表達式不同,表達式必須完全匹配,數(shù)據(jù)必須跟模式嚴格匹配。
[root@test]# cat data.txt data11,data12,data13 data21,data22,data23 data31,data32,data33gawk -F ',' '$1 == "data" {print $0}' data.txt[root@test]# gawk -F ',' '$1 == "data" {print $0}' data.txt[root@test]# gawk -F ',' '$1 == "data11" {print $0}' data.txt data11,data12,data13由實例結(jié)果可以看到,第一個測試沒有匹配任何記錄,因為第一個數(shù)據(jù)字段值不在任何記錄中,第二個測試用值data11匹配了一條記錄。
(3)格式化打印
print 語句在gawk如何顯示數(shù)據(jù)上并未提供多少控制。你能做的只是控制輸出字段分隔符( OFS )。格式化打印命令,叫作 printf 。如果你熟悉C語言編程的話,gawk中的printf 命令用法也是一樣,允許指定具體如何顯示數(shù)據(jù)的指令。
printf 命令的格式:
printf "format string", var1, var2 . . .format string 是格式化輸出的關(guān)鍵。它會用文本元素和格式化指定符來具體指定如何呈現(xiàn)格式化輸出。格式化指定符是一種特殊的代碼,會指明顯示什么類型的變量以及如何顯示。gawk程序會將每個格式化指定符作為占位符,供命令中的變量使用。第一個格式化指定符對應列出的第一個變量,第二個對應第二個變量,依此類推。格式化指定符采用如下格式:
?
其中 control-letter 是一個單字符代碼,用于指明顯示什么類型的數(shù)據(jù),而 modifier 則定義了可選的格式化特性。
控制字母?? ?描 述 c?? ? 將一個數(shù)作為ASCII字符顯示 d?? ? 顯示一個整數(shù)值 i?? ?顯示一個整數(shù)值(跟d一樣) e?? ?用科學計數(shù)法顯示一個數(shù) f?? ? 顯示一個浮點值 g?? ? 用科學計數(shù)法或浮點數(shù)顯示(選擇較短的格式) o?? ? 顯示一個八進制值 s?? ? 顯示一個文本字符串 x?? ? 顯示一個十六進制值 X?? ? 顯示一個十六進制值,但用大寫字母A~F因此,如果你需要顯示一個字符串變量,可以用格式化指定符 %s 。如果你需要顯示一個整數(shù)值,可以用 %d 或 %i ( %d 是十進制數(shù)的C風格顯示方式)。如果你要用科學計數(shù)法顯示很大的值,就用 %e 格式化指定符。
gawk 'BEGIN{x = 10 * 100 ;printf "The answer is: %d\n", x}'[root@test]# gawk 'BEGIN{x = 10 * 100 ;printf "The answer is: %d\n", x}' The answer is: 1000除了控制字母外,還有3種修飾符可以用來進一步控制輸出。
width :指定了輸出字段最小寬度的數(shù)字值。如果輸出短于這個值, printf會將文本右對齊,并用空格進行填充。如果輸出比指定的寬度還要長,則按照實際的長度輸出。 prec :這是一個數(shù)字值,指定了浮點數(shù)中小數(shù)點后面位數(shù),或者文本字符串中顯示的最大字符數(shù)。 -(減號):指明在向格式化空間中放入數(shù)據(jù)時采用左對齊而不是右對齊。 [root@test]# cat data2.txt riley mullen 123 main street chicago,IL 38383 (312)555-1234frank will 456 oak street indianapolis,in 345 (317)555-9876gawk 'BEGIN{FS="\n"; RS=""} {print $1,$4}' data2.txt [root@test]# gawk 'BEGIN{FS="\n"; RS=""} {print $1,$4}' data2.txt riley mullen (312)555-1234 frank will (317)555-9876可以用 printf 命令來幫助格式化輸出,使得輸出信息看起來更美觀。首先,讓我們將 print命令轉(zhuǎn)換成 printf 命令,看看會怎樣。gawk 'BEGIN{FS="\n"; RS=""} {printf "%s %s\n", $1, $4}' data2.txt[root@test]# gawk 'BEGIN{FS="\n"; RS=""} {printf "%s %s\n", $1, $4}' data2.txt riley mullen (312)555-1234 frank will (317)555-9876它會產(chǎn)生跟 print 命令相同的輸出。 printf 命令用 %s 格式化指定符來作為這兩個字符串值的占位符。注意,你需要在 printf 命令的末尾手動添加換行符來生成新行。沒添加的話, printf 命令會繼續(xù)在同一行打印后續(xù)輸出。?
printf 命令在處理浮點值時也非常方便。通過為變量指定一個格式,你可以讓輸出看起來更統(tǒng)一。下面的例子中使用 %5.1f 格式指定符來強制 printf 命令將浮點值近似到小數(shù)點后一位。
cat test.txt 130 120 135 110 879 675 234 567 356gawk '{ total = 0 for (i = 1; i < 4; i++) { total += $i } avg = total / 3 printf "Average: %5.1f\n",avg }' test.txt[root@test]# gawk '{ > total = 0 > for (i = 1; i < 4; i++) > { > total += $i > } > avg = total / 3 > printf "Average: %5.1f\n",avg > }' test.txt Average: 128.3 Average: 554.7 Average: 385.7通過添加一個值為 16 的修飾符,我們強制第一個字符串的輸出寬度為16個字符。默認情況下,printf 命令使用右對齊來將數(shù)據(jù)放到格式化空間中。要改成左對齊,只需給修飾符加一個減號即可。
[root@test]# cat data2.txt riley mullen 123 main street chicago,IL 38383 (312)555-1234frank will 456 oak street indianapolis,in 345 (317)555-9876gawk 'BEGIN{FS="\n"; RS=""} {printf "%16s %s\n", $1,$4}' data2.txt[root@test]# gawk 'BEGIN{FS="\n"; RS=""} {printf "%16s %s\n", $1,$4}' data2.txtriley mullen (312)555-1234frank will (317)555-9876gawk 'BEGIN{FS="\n"; RS=""} {printf "%-16s %s\n", $1,$4}' data2.txt [root@test]# gawk 'BEGIN{FS="\n"; RS=""} {printf "%-16s %s\n", $1,$4}' data2.txt riley mullen (312)555-1234 frank will (317)555-9876?
總結(jié)
以上是生活随笔為你收集整理的gawk程序的简单使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 郭天祥嵌入式开发教程
- 下一篇: DvaJS的Subscription的使