![]() |
![]() |
![]() |
![]() |
![]() |
$ export TIME_STYLE=long-iso ←設時間格式(不同環境設定會影響〝ls -l〞的輸出格式) | |||||||
$ ls -l | |||||||
drwxr-xy-x | 2 | aaa | aaa | 4096 | 2011-09-07 | 11:44 | Desktop |
drwxr-xy-x | 2 | aaa | aaa | 4096 | 2011-09-07 | 11:44 | Documents |
drwxr-xy-x | 2 | aaa | aaa | 4096 | 2011-09-07 | 11:44 | Music |
drwxr-xy-x | 2 | aaa | aaa | 4096 | 2011-09-07 | 11:44 | Pictures |
drwxr-xy-x | 2 | aaa | aaa | 4096 | 2011-09-07 | 11:44 | Public |
↑ | ↑ | ↑ | ↑ | ↑ | ↑ | ↑ | ↑ |
$1 | $2 | $3 | $4 | $5 | $6 | $7 | $8 ←欄位變數 |
變數 | 內容 | 註 |
$0 | drwxr-xy-x 2 aaa aaa 4096 2011-09-07 11:44 Desktop | $0 內容為一整行 |
$1 | drwxr-xy-x | 欄位=1的字串 |
$2 | 2 | 欄位=2的字串 |
$3 | aaa | 欄位=3的字串 |
$4 | aaa | 欄位=4的字串 |
$5 | 4096 | 欄位=5的字串 |
$6 | 2011-09-07 | 欄位=6的字串 |
$7 | 11:44 | 欄位=7的字串 |
$8 | Desktop | 欄位=8的字串 |
$ ls -l | awk '{print $5,$8}'←只輸出欄位 5 和 8 4096 Desktop 4096 Documents 4096 Music 以下略 |
$ ls -l | awk '{print "File",$8,"size =",$5,"Byte"}' File Desktop size = 4096 Byte File Documents size = 4096 Byte File Music size = 4096 Byte 以下略 |
$ ls -l | awk '{print "File",$8,"size =",$5/1024,"KB"}' File Desktop size = 4 KB File Documents size = 4 KB File Music size = 4 KB 以下略 $ ls -l | awk '{print "File",$8,"size =",$5/1024,"KB"}' > reformate.txt ←將新的輸出存成檔案〝reformat.txt〞 |
$ awk '{print $1*$2}' - ←最後面的〝-〞 為標準輸入(鍵盤) 3.14 1.41421 ←任意輸入兩個數字 4.44062 ←輸出相乘結果 (按 <Ctrl-D> 來結束) |
$ cat awk_scr ←例如有一外部 script 檔〝awk_scr〞,內容如下 {print "File",$8,"size =",$5/1024,"KB"} $ ls -l | awk -f awk_scr ←用選項〝-f〞來使用外部的 script 檔〝awk_scr〞 |
$ cat awk_scr1 ←例如有一檔〝awk_scr1〞,內容如下 awk '{print "File",$8,"size =",$5/1024,"KB"}' $ chmod +x awk_scr1 ←讓〝awk_scr1〞具有可執行的權限 $ ls -l | ./awk_scr1 ←執行〝awk_scr1〞 |
awk relational operators | |
Operator | Meaning |
== | 相等 |
!= | 不相等 |
> | 大於 |
>= | 大於或等於 |
< | 小於 |
<= | 小於或等於 |
&& | 條件的 AND 判斷 |
|| | 條件的 OR 判斷 |
awk relational operators | ||
Operator | Meaning | Note |
字串~ /正規表示法/[動作(actions)] | 字串如可匹配正規表示法,則執行 Actions | [註] |
字串 ! ~ /正規表示法/[動作] |
字串如無法匹配正規表示法,則執行 Actions | |
/正規表示法/[動作] |
目前讀入的行如可匹配正規表示法,則執行 Actions (省略字串和和符號〝~〞的敘述,會用 $0 來匹配正規表示法) |
|
!/正規表示法/[動作] |
目前讀入的行如無法匹配正規表示法,則執行 Actions |
List of awk syntax | Note |
if ( conditional ) statement [ else statement ] while ( conditional ) statement do {statement} while (conditional) for ( expression ; conditional ; expression ) statement for ( variable in array ) statement break continue { [ statement ] ...} variable=expression [command][&][|]getline [var][<][ file] print [ expression-list ] [ > expression ] printf ( ) format [ , expression-list ] [ > expression ] function( ) next exit |
參考來源 http://www.grymoire.com/Unix/Awk.html |
$ cat awk_scr2 BEGIN { brand="555" #←變數〝brand〞= 字串 "555" unit_price = 0.8 #←變數〝unit_price〞= 數值 0.8 dozen = 12 #←變數〝dozen〞= 數值 12 print brand,"cigarettes a dozen price=",unit_price * dozen } $ awk -f awk_scr2 555 cigarettes a dozen price= 9.6 |
$ cat awk_m_table BEGIN{ #←awk of Multiplication Table example for( i=1; i<=9; i++ ){ for( j=1; j<=9; j++ ){ array[i, j] = i * j print i" * "j" = "array[i,j] } } } $ awk -f awk_m_table 1 * 1 = 1 1 * 2 = 2 中間略 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81 |
$ echo 'ab cd ef' | awk '{print NF}' ←因有三個欄位故 NF=3 3 |
awk built-in variables | ||||
Variable | Meaning | Default | Regular-Eexpression support |
Note |
ARGC | 輸入參數 count input arguments count |
- | ||
ARGV | 輸入參數 vecter input arguments vecter |
- | ||
FILENAME | 目前所讀取資料的檔名 name of current input file |
- | ||
FNR | 目前檔案所讀入的列數 record number in current file |
- | ||
FS | 輸入欄位間隔 input field separator |
blank& tab | Yes | 參考 BEGIN 範例 |
IGNORECASE | (非零值時)匹配時不管大小寫 ignoring case sensitivity |
1 | Yes | gun 版本的 gawk 有支援此內建變數 |
NF | 目前列的欄位數 number of fields in current record |
- | ||
NR | awk 所累計讀入的列數 number of records read so far |
- | 參考 END 範例 | |
OFMT | 數值輸出格式 output format for numbers |
%.6g | 參考 print 範例 | |
OFS | 輸出欄位間隔 output field separator |
blank | 參考 print 範例 | |
ORS | 輸出列間隔 output record separator |
newline | ||
RS | 輸入列間隔 input record separator |
newline | Yes | |
RSTART | 字串函數 match 的第一個字元索引 index of first character matched by match |
- | 參考字串函數 | |
RLENGTH | 字串函數 match 的長度匹配 match length of string matched by match |
- | 參考字串函數 | |
SUBSEP | 矩陣分隔字元 subscript separator |
"\034" | 參考關聯矩陣 |
$ cat awk_scr3 BEGIN { FS="[:-]" #←設定欄位間隔為〝:〞或〝-〞 } { for( i=1; i<=NF; i++ ) print $i } $ echo "ab-cd ef:gh-ij" | awk -f awk_scr3 ab cd ef gh ij |
[BEGIN { statement }] |
[{main}] |
[END{ statement }] |
特別注意這三大塊各別用中括號〝[ ]〞括起來表示不一定要同時存在,〝BEGIN {}〞為當資料還沒讀進來時就先執行的部份,而〝END {}〞為資料都讀完才去執行的部份,故〝BEGIN {}〞和〝END {}〞只會各執行一次。而〝{main}〞內為主程式是每筆資料進來都會被執行。
所以 BEGIN {} 時常用來作初始設定,而 END {} 用來跑結束時的運算結果,而每筆資料進來都要運算的部分就放在 {main}。
例如〝/etc/shadow〞 檔內的欄位間隔為〝:〞並非空白,我可以在檔案都還沒讀進來時在 BEING {}區塊內設定欄位間隔為〝:〞(設定內建變數 FS=":"),而會讀入每筆資料的{main}區塊內檢查看欄位 2 是否為空白來找出看誰沒設帳號密碼。實例如下:
例:(以 root 登入測試才可讀取檔案〝/etc/shadow〞)
# cat awk_nopasswd ←找出沒設帳號密碼的程式
BEGIN { # ←BEGIN{}區塊
FS=":" # ←設定欄位間隔為〝:〞
total=0 # ←初始自定變數值為 0
}
{ #←主程式區塊
if ( $2 == "" )
{
print $1 ": no password"
total ++
}
}
END { print "Total no password account=",total} #←END {}區塊
# cat /etc/shadow | awk -f awk_nopasswd ←執行〝找出沒設帳號密碼的程式〞
john: no password
fossett: no password
Total no password account= 2
如果某一程式不用讀取任何檔案,我可以寫在 BEGIN {} 內 。
例:
$ awk 'BEGIN{print "Hello AWK"}'
Hello AWK
上例中如 print 寫在 END{}區塊內,因沒任何資料會讀入,故永遠不會被執行。如寫在 {main} 區塊,如下例 ls | awk '{print "Hello AWK"}',則不管三七二十一,有資料讀入就輸出一次〝Hello AWK〞。
所以 END {}區塊為用來跑結束時的運算結果,如下例為在 END {}區塊內印出內建變數〝NR〞就可知檔案共有多少行(模擬指令 wc -l) 。
例:
$ awk 'END {print NR}' /usr/share/dict/linux.words ←模擬指令 wc -l
479829
$ awk '/^ayy*/,/^azz*/' /usr/share/dict/linux.words ←列出字典中 ay 到 az 開頭的所有的單字 |
$ awk 'BEGIN {print "hello","awk"}' ←print 內的逗號〝,〞代表一個輸出欄位間隔,預設為空白 hello awk $ awk 'BEGIN {OFS="<-->";print "hello","awk"}' ←更改輸出欄位間隔為〝<-->〞(輸出欄位間隔的內建變數為〝OFS〞) hello<-->awk |
$ awk 'BEGIN{print 0123456789.0123456789}' ←預設輸出為 6 位數的科學符號 1.23457e+08 $ awk 'BEGIN{OFMT="%.3f";print 0123456789.0123456789}' ←改小數點三位的浮點輸出 123456789.012 $ awk 'BEGIN{OFMT="%d";print 0123456789.0123456789}' ←改整數輸出 123456789 |
$ awk 'BEGIN{ printf ("%d %s %1.2f\n",2,"Cheeseburgers",4.699)}' 2 Cheeseburgers 4.70 |
awk printf format | |
符號 | 資料型別 |
%c | ASCII 字元 |
%d | 整數 |
%e | 科學符號 |
%f | 浮點 |
%g | awk 自動判斷使用科學符號或浮點 |
%o | 八進位制 |
%s | 字串 |
%x | 十六進位制 |
awk printf format for width | |
符號 | 資料型別 |
%f | 不指定寬度的浮點(系統預設) |
%3d | 3位數的整數 |
%.2f | 兩位的小數寬度的浮點 |
%2.f | 兩位的整數寬度的浮點 |
$ awk 'BEGIN{ printf ("%f \n",4.699)}' ←只指定浮點,但不指定寬度 4.699000 $ awk 'BEGIN{ printf ("%.2f \n",4.699)}' ←兩位的小數寬度 4.70 $ awk 'BEGIN{ printf ("%2.f \n",4.699)}' ←只用浮點的整數部分(自動四捨五入) 5 $ awk 'BEGIN{ printf ("%3d \n",4.699)}' ←三位數的整數(無條件捨去小數) 4 |
$ echo 65 66| awk '{printf ("%10c%10c \n",$1,$2)}' ←輸出 10 位寬度的 ASCII 65 & 66 (靠右輸出) A B $ echo 65 66| awk '{printf ("%10c%-10c \n",$1,$2)}' ←強迫第二個字元靠左輸出 AB |
RED | BLUE | ←索引字串 |
2.1 | "TV" | ←內容 |
$ awk 'BEGIN{color["RED"]=2.1;color["BLUE"]="TV";print color["RED"],color["BLUE"]}' 2.1 TV ←color["RED"] 內容為〝2.1〞& color["BLUE"] 內容為〝TV〞 |
$ awk 'BEGIN{color["RED"]=2.1;color["BLUE"]="TV";for (i in color) print i,color[i]}' BLUE TV RED 2.1 |
$ cat parts.db KEYBOARD white black MOUSE blue red black white yellow CASE black MONITOR white silver red |
$ cat awk_scr4 ←統計每一種顏色出現的次數的程式 { for( i=2; i<=NF; i++ ) color[$i]++ #←同等 color[$i] = color[$i] +1 } END { for( j in color ) printf( "%10s %d \n", j, color[j] ) } $ awk -f awk_scr4 parts.db ←執行〝awk_scr4〞來統計檔案〝parts.db〞 red 2 white 3 black 3 blue 1 silver 1 yellow 1 |
$ awk 'BEGIN{arrayA[3,7]="INDIGO";print arrayA["3\0347"];print arrayA[3,7]}' INDIGO ←arrayA[3,7] 等於 arrayA["3\0347"] 故輸出結果是一樣的 INDIGO |
指令 | note |
delete array_name | 刪除整個矩陣 |
delete array_name["string"] | 刪除關聯矩陣內的一個儲存格(一維) |
delete array_name[2,3] | 刪除關聯矩陣內的一個儲存格(二維) |
delete array_name [10] | 刪除關聯矩陣內的一個儲存格(一維) |
$ cat awk_scr5 { for( i=2; i<=NF; i++ ) color[$i]++ delete color ["yellow"] #←刪除關聯矩陣人的一個儲存格〝color ["yellow"]〞 } 以下略 |
$ cat awk_scr6 BEGIN { #←BEGIN 區塊 outfile = "result" } { #←主程式區塊 for( i=2; i<=NF; i++ ) color[$i]++ } END { #←END 區塊 for( j in color ) printf( "%10s %d \n", j, color[j] ) > outfile #←結果重定向到檔案 print "***** Result Statistics *****" > outfile #←輸出重定向到檔案 } $ awk -f awk_scr6 parts.db ←執行〝awk_scr6〞(檔案〝parts.db〞同關聯矩陣範例) $ cat result ←查看檔案〝result〞 red 2 white 3 black 3 blue 1 silver 1 yellow 1 ***** Result Statistics ***** |
$ cat awk_scr7 略 (BEGIN 和主程式區塊同〝awk_scr6〞) END { for( j in color ) printf( "%10s %d \n", j, color[j] ) > outfile print "***** Result Statistics *****" > outfile system ("cat "outfile) # ←執行系統指令〝cat〞 } |
$ cat awk_scr8 BEGIN { print "abc" > "fileA" # ←建立檔案〝fileA〞 print "123" > "fileA" # ←累加重定向到〝fileA〞 } $ awk -f awk_scr8 $ cat fileA abc 123 $ cat awk_scr9 BEGIN { print "abc" > "fileA" # ←建立檔案〝fileA〞 close ("fileA") # ←關閉〝fileA〞(切斷檔案的指標連結) print "123" > "fileA" #指標連結被切斷,故此為建立檔案〝fileA〞 } $ awk -f awk_scr9 $ cat fileA 123 ←後面的結果蓋掉前一結果 |
$ cat awk_scr10 BEGIN { print "abc" | "tr 'a-z' 'A-Z' > fileA" #←輸出經管線用 tr 把小寫改大寫 close ("tr 'a-z' 'A-Z' > fileA") #←close ("管線之後的 COMMAND")要一字不漏的寫進 close 內 system ("echo '123' >>" "fileA") #←〝fileA〞指標連結被切斷(close 了)故如要累加要用累加重定向〝>>〞 } $ awk -f awk_scr10 $ cat fileA ABC 123 |
$ seq 1 10 | awk 'BEGIN{getline;print}' ← 一次只讀一行 1 $ seq 1 10 | awk '{getline;print}' ←getline 如寫在主程式區是讀到下一行,所以輸出是跳行 2 4 6 8 10 |
getline 讀取 record |
|
成功 | 1 |
失敗 | -1 |
檔案結束 (〝EOF〞End Of File ) | 0 |
$ seq 1 2 | awk 'BEGIN{print getline; print getline; print getline}' 1 ←getline 讀取成功 ($0=1) ,傳回值=1 1 ←getline 讀取成功 ($0=2) ,傳回值=1 0 ←getline 讀取失敗 ($0=EOF) ,傳回值=0 |
$ seq 1 3 | awk 'BEGIN{while (getline) print}' ←因檔案結束時 getline 會 return 0 而跳出while
迴圈) 1 2 3 |
getline [var] | 單獨使用,讀入目前的行存於欄位變數 |
getline [var] < "FILE" | 從檔案讀取資料 |
"COMMAND" | getline [var] | 從指令的輸出讀取資料 |
$ cat awk_scr11 { /\/$/ #←等於〝if ($0 ~/\/$/)〞(如果檔名是目錄,則繼續後續的動作,否則就處理下個檔名) { DirName=$0; while (("ls -A " DirName )| getline)#←用 getline 讀取系統指令〝ls -A〞的輸出 ListCount++ if (ListCount == 0) # ←假如 ListCount=0,一定是空目錄 {print "Directory --> "DirName" is empty"} ListCount=0 } } $ ls -F | awk -f awk_scr11 Directory --> dir2 is empty Directory -- >Documents is empty Directory --> Download is empty |
數學函數名 | 說明 | 範例 | 範例返回值 |
% | 餘數 | 7%5 | 2 |
^ | 指數 | 2^3 | 8 |
數學函數名 | 說明 | 範例 | 範例返回值 |
sin( x ) | 正弦;其中 x 為弧度(弧度 = 角度/180 * PI) | sin (90 /180 * 3.4146) | 1 |
cos( x ) | 餘弦;其中 x 為是弧度〝radian〞(弧度 = 角度/180 * PI) | cos (180/180*3.1416) | - 1 |
atan2( y, x ) | 反正切 arc-tangent (y/x)反正切,傳回值為徑度 | atan2(30,45) | 0.588003 |
exp( x ) | ex | exp(1) | 2.71828 |
log( x ) | log e x | log (5) | 1.60994 |
sqrt( x ) | 開根號 | sqrt (9) | 3 |
int( x ) | 整數值(無條件去小數) | int (5.6) | 5 |
rand( ) | 亂數;其中 0 <=亂數 < 1 | ||
srand( [x] ) | 初始化 rand(),x 為亂數種子(seed),若省略,則會以執行時的時間+日期為起始的亂數種子 |
$ awk 'BEGIN{for (i=1;i<=10;i++) print rand()}' 0.237788 0.291066 0.845814 0.152208 0.585537 0.193475 0.810623 0.173531 0.484983 0.151863 |
$ awk 'BEGIN{srand();for (i=1;i<=10;i++) print rand()}' ←用〝srand()〞來初始化〝rand()〞的亂數種子 |
$ awk 'BEGIN{srand();for (i=1;i<=6;i++) print int(rand()*49)+1}' ←〝明牌〞產生器 輸出略 |
$ awk 'BEGIN{"echo '$((2#1100))' " | getline dec ;print dec}' 12 |
$ awk 'BEGIN{str1="123";str2= str1 "abc"; print str2}' 123abc |
字串函數 | 說明 | 範例 | 範例返回值 |
sub(regex, replace [,string] ) | 取代一筆字串 | st1="google goooogle" sub(/go+g/,"YAHOO",st1) |
1 st1="YAHOOle goooogle" |
gsub regex,replace [,string ] ) | 取代全部字串 | st1="google goooogle" gsub(/go+g/,"YAHOO",st1) |
2 st1="YAHOOle YAHOOle" |
index(string, substring) | 返回 substring 在 string 的位置, | index("this","is") | 3 |
match(string,regex ) | 返回正規表示法匹配 string 的位置和長度 |
match("123xyzxyzxyz456",/(xyz)+/) | RSTART=4 RLENGTH=9 |
length [(string)] | 返回字串長度 | length ("yahoo") | 5 |
substr(string, index [,length] ) | 返回抽取後的字串 | substr("12345678',3,4} | "3456" |
split(string, Array [,regex] ) | 將字串切割放入矩陣 | split("abc:de-fgh",arrA,/[:-]/ | arraA[1]="abc" arraA[2]="de" arraA[3]="fgh" |
tolower( string ) | 大寫轉小寫 | tolower("Yahoo! 123") | "yahoo! 123" |
toupper( string ) | 小寫轉大寫 | toupperr("Yahoo! 123") | "YAHOO! 123" |
sprintf(format, data1,data2 ... ) | 將 printf 的輸出變新字串 | sprintf("%.4f",3.14162654) | 3.1416 |
$ echo "google goooogle" |awk '{sub(/go+g/,"YAHOO");print }' ←如字串〝google goooogle〞可被正規表示法的〝go+g〞匹配,則用〝YAHOO〞取代之且只取代一次 YAHOOle goooogle |
$ awk 'BEGIN{st1="google gooooogle";print gsub(/go+g/,"YAHOO",st1);print st1}' 2 ←加了〝print gsub()〞會返回取代的次數 YAHOOle YAHOOle ←取代結果 |
$ echo 'this' | awk '{print index($0,"is")}' 3 |
$ echo '123xyzxyzxyz456' | awk '{match($0,/(xyz)+/); print RSTART,RLENGTH}' 4 9 |
$ echo 'yahoo' | awk '{print length()}' 5 |
$ echo '123456789' | awk '{print substr($0,3,4)}' 3456 $ echo '123456789' | awk '{print substr($0,3)}' 3456789 |
$ echo "abc de fgh" | awk '{split($0,arrayA);for (i in arrayA) print arrayA[i]}' abc de fgh |
$ awk 'BEGIN{print tolower("Yahoo! 123")}' yahoo! 123 $ awk 'BEGIN{print toupper("Yahoo! 123")}' YAHOO! 123 |
$ echo '3.141592654' | awk '{new=sprintf("%.4f",$0);print new}' 3.1416 |
$ cat awk_abs { print abs($0) # ←call 自定絕對值函數〝abs()〞 } function abs (value) # ←自定的絕對值函數〝abs()〞 { if(value <0) value = value * (-1) return value # ←如有返回值用 return } $ echo "-13.38" | awk -f awk_abs 13.38 |