1. 程式人生 > >awk從簡單到復雜

awk從簡單到復雜

awk shell

1、語法和參數說明

語法

awk [options] 'script' var=value file(s)

awk [options] -f scriptfile var=value file(s)

awk [options] 'pattern{action}' FILE ....


選項參數說明:

-F fs or --field-separator fs

指定輸入文件折分隔符,fs是一個字符串或者是一個正則表達式,如-F:。

-v var=value or --asign var=value

賦值一個用戶定義變量。

-f scripfile or --file scriptfile

從腳本文件中讀取awk命令。

-mf nnn and -mr nnn

對nnn值設置內在限制,-mf選項限制分配給nnn的最大塊數目;-mr選項限制記錄的最大數目。這兩個功能是Bell實驗室版awk的擴展功能,在標準awk中不適用。

-W compact or --compat, -W traditional or --traditional

在兼容模式下運行awk。所以gawk的行為和標準的awk完全一樣,所有的awk擴展都被忽略。

-W copyleft or --copyleft, -W copyright or --copyright

打印簡短的版權信息。

-W help or --help, -W usage or --usage

打印全部awk選項和每個選項的簡短說明。

-W lint or --lint

打印不能向傳統unix平臺移植的結構的警告。

-W lint-old or --lint-old

打印關於不能向傳統unix平臺移植的結構的警告。

-W posix

打開兼容模式。但有以下限制,不識別:/x、函數關鍵字、func、換碼序列以及當fs是一個空格時,將新行作為一個域分隔符;操作符**和**=不能代替^和^=;fflush無效。

-W re-interval or --re-inerval

允許間隔正則表達式的使用,參考(grep中的Posix字符類),如括號表達式[[:alpha:]]。

-W source program-text or --source program-text

使用program-text作為源代碼,可與-f命令混用。

-W version or --version

打印bug報告信息的版本。


其中pattern包括以下幾種:

地址定界

模式(包括正則表達式)

表達式

BEGIN(命令執行前預處理操作)

END(命令執行後的操作)


pattern通過,才會執行{action},當然pattern也可以省去,不匹配只執行動作。


action:

定義變量(數組)

語句(if、while、for)

輸出(print、printf)


awk內置的變量:

NF : 當前處理行一共多少字段

FS : 輸入字段分隔符,默認空格

OFS : 輸出字段分隔符,默認空格

NR : 目前awk所處理的是第幾行數據

2、基本用法

示例1:

打印用戶為apache和zabbix用戶的用戶名、UID、處理行的字段總數、輸出行處於文件的第幾行、輸出符合條件的行最後一列

方法1:

# awk -F: 'BEGIN{OFS="*"} /^apache|^zabbix/ {print $1,$3,NF,NR,$NF}' /etc/passwd

zabbix*498*7*30*/sbin/nologin

apache*48*7*36*/sbin/nologin


方法2:

# awk 'BEGIN{FS=":";OFS="*"} /^apache|^zabbix/ {print $1,$3,NF,NR,$NF}' /etc/passwd

zabbix*498*7*30*/sbin/nologin

apache*48*7*36*/sbin/nologin


解析:

分隔符:有兩種表示方法,如方法1所示使用-F跟分隔符的方式,方法2中和輸出分隔符OFS一塊放入BEGIN{}模塊,默認輸出分隔符是空格。


NF:

表示文件內容的列數,所以$NF就表示最後一列。


模式:

/^apache|^zabbix/ 就是模式的匹配,模式寫入//就可以,表示匹配以apache或者zabbix開頭的行。


BEGIN:

在awk實際工作之前執行一次

舉例:

# awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd

root 0

bin 1

...


# awk '{FS=":"} {print $1,$3}' /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin 1

...


可以看到第二個輸出結果和第一個結果不一樣,因為BEGIN的工作流程是這樣的:1、沒有BEGIN出現,不用事前執行一些動作;2、awk開始獲取第一行數據,以FS值為分隔符,此時的FS是空的,$0變量保存整行數據,$1保存第一個字段數據,$2保存第二個字段數據.........一直到最後;3、awk開始執行動作,FS=":" ---> 顯示$1,$3 ---> 獲取第二行數據,以FS值冒號為分隔符............。


在FS賦值之間就已經把第一行數據獲取完畢了。 所以 在有BEGIN的情況下,awk在獲取數據之前會執行一次BEGIN的動作, 而且只有這一次。 那麽END也就不難理解了,就是在操作完所有行數據以後所執行的一次動作。


示例2:

print和printf

# awk 'BEGIN{FS=":"}NR==5,NR==8{print $1,$3,"\t\t","This is",NR,"line"}' /etc/passwd

lp 4 This is 5 line

sync 5 This is 6 line

shutdown 6 This is 7 line

halt 7 This is 8 line


解析:

NR是表示第幾行,上面就是第5行到第8行的定界

在print裏面除了變量以外,其它字符都要加上引號。\t表示一個制表符TAB。不同的字段輸出的時候會以輸出字符分隔符隔開

除了表示字段數據的$0,$1,$2等,其他變量包括自定義變量都不用$號


但是可以明顯感覺上面的排版有點亂,這裏可以使用printf對輸出內容進行格式化。


下面進行格式化輸出

# awk 'BEGIN{FS=":"}NR==5,NR==8{printf "%-10s %5s %10s %2s %5s\n",$1,$3," This is",NR,"line"}' /etc/passwd

lp 4 This is 5 line

sync 5 This is 6 line

shutdown 6 This is 7 line

halt 7 This is 8 line


解析:

格式化常用格式化字符

\n 換行

\t 水平TAB鍵


%s 顯示字符串。 數值也可以當作字符串顯示

%d,%i 十進制整數。

%c 顯示字符ASCLL碼。

%e,%E 科學計數法顯示數值。

%f 浮點數顯示。

%n.mf n表示包括小數點在內的長度,m表示小數點後的長度。

%% 顯示%自身。

%u 無符號整數

修飾符:

- 左對齊

+ 顯示數值符號

0 以0代替多余的空格。

這裏需要註意的是%-10s %5s %10s %2i%5s\n這一段就是格式化語句,%-10s:表示10個字符寬度,“-”表示左對齊,printf不會自動換行,所以後面加了個\n。


示例3:表達式

匹配UID大於等於500的相應信息

# awk 'BEGIN{FS=":"}$3>=500{printf "%-10s %5s %10s %2s %5s\n",$1,$3,"This is",NR,"line"}' /etc/passwd

nfsnobody 65534 This is 23 line

nexus 500 This is 31 line

box 501 This is 32 line


示例4:添加說明

對上面的輸出添加說明

# awk 'BEGIN{FS=":";printf "%-10s %5s %12s %17s\n","USER","UID","SHELL","DESCRIPTION"}/bin\/bash\>/{printf "%-10s %5s %15s %10s %2i%5s\n",$1,$3,$7,"This is",NR,"line"}' passwd

USER UID SHELL DESCRIPTION

root 0 /bin/bash This is 1 line

nexus 500 /bin/bash This is 31 line

...


示例5:算數和自定義變量

計算同學總成績

# cat test.txt

User English Math Music

zhangsan 85 90 83

lisi 80 95 60

zhouwu 66 77 98

zhengwang 80 93 67


# awk 'NR==1{printf "%-10s %7s %6s %6s %6s\n",$1,$2,$3,$4,"Total"}NR>=2{total=$2+$3+$4;printf "%-10s %7s %6s %6s %6s\n",$1,$2,$3,$4,total}' test.txt

User English Math Music Total

zhangsan 85 90 83 258

lisi 80 95 60 235

zhouwu 66 77 98 241

zhengwang 80 93 67 240


解析:

NR==1表示第一行在第五列定義了一個字符串“Total”,也就是定義了一個變量。

NR>=2之後的內容表示當行數大於等於2的時候,每一行的Total的值等於第二列第三列和第四列的值相加。


未完待續...


參考:

http://f.dataguru.cn/thread-509133-1-1.html


awk從簡單到復雜