AWK介紹

AWK介紹
0.awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk。
1.awk語言的最基本功能是在文件或字符串中基於指定規則來分解抽取信息,也可以基於指定的規則來輸出數據。完整的awk腳本通常用來格式化文本文件中的信息。

2.三種方式調用awk
1) awk [opion] 'awk_script' input_file1 [input_file2 ...]
awk的常用選項option有;
① -F fs : 使用fs作爲輸入記錄的字段分隔符,如果省略該選項,wak使用環境變量IFS的值
② -f filename : 從文件filename中讀取awk_script
③ -v var=value : 爲awk_script設置變量
2) 將awk_script放入腳本文件並以 #!/bin/awk -f 作爲首行,給予該腳本可執行權限,然後在shell下通過鍵入該腳本的腳本名調用之。
3) 將所有的awk_script插入一個單獨腳本文件,然後調用: awk -f wak腳本文件 input_file(s)

3. awk的運行過程
1) awk_script的組成:
① awk_script可以由一條或多條awk_cmd組成,兩條awk_cmd之間一般以NEWLINE分隔
② awk_cmd由兩部分組成: awk_pattern { actions }
③ awk_script可以被分成多行書寫,必須確保整個awk_script被單引號括起來。
2) awk命令的一般形式:
awk ' BEGIN { actions }
awk_pattern1 { actions }
............
awk_patternN { actions }
END { actions }
' inputfile
其中 BEGIN { actions } 和 END { actions } 是可選的。
3) awk的運行過程:
① 如果BEGIN 區塊存在,awk執行它指定的actions。
② awk從輸入文件中讀取一行,稱爲一條輸入記錄。(如果輸入文件省略,將從標準輸入讀取)
③ awk將讀入的記錄分割成字段,將第1個字段放入變量$1中,第2個字段放入$2,以此類推。$0表示整條記錄。字段分隔符使用shell環境變量IFS或由參數指定。
④ 把當前輸入記錄依次與每一個awk_cmd中awk_pattern比較,看是否匹配,如果相匹配,就執行對應的actions。如果不匹配,就跳過對應的actions,直到比較完所有的awk_cmd。
⑤ 當一條輸入記錄比較了所有的awk_cmd後,awk讀取輸入的下一行,繼續重複步驟③和④,這個過程一直持續,直到awk讀取到文件尾。
⑥ 當awk讀完所有的輸入行後,如果存在END,就執行相應的actions。

4) iput_file可以是多於一個文件的文件列表,awk將按順序處理列表中的每個文件。
5) 一條awk_cmd的awk_pattern可以省略,省略時不對輸入記錄進行匹配比較就執行相應的actions。一條awk_cmd的actions 也可以省略,省略時默認的動作爲打印當前輸入記錄(print $0) 。一條awk_cmd中的awk_pattern和actions不能同時省略。
6) BEGIN區塊和END區塊別位於awk_script的開頭和結尾。awk_script中只有END區塊或者只有BEGIN區塊是被允許的。如果awk_script中只有BEGIN { actions } ,awk不會讀取input_file。
7) awk把輸入文件的數據讀入內存,然後操作內存中的輸入數據副本,awk不會修改輸入文件的內容。
8) awk的總是輸出到標準輸出,如果想讓awk輸出到文件,可以使用重定向。

4.awk_pattern
awk_pattern模式部分決定actions動作部分何時觸發及觸發actions。awk_pattern可以是以下幾種類型:
1) 正則表達式用作awk_pattern: /regexp/
① awk中正則表達式匹配操作中經常用到的字符:
/ ^ $ . [] | () * // 通用的regexp元字符
+ : 匹配其前的單個字符一次以上,是awk自有的元字符,不適用於grep或sed等
? : 匹配其前的單個字符1次或0次,是awk自有的元字符,不適用於grep或sed等
② 舉例:
awk '/ */$0/.[0-9][0-9].*/' input_file
2) 布爾表達式用作awk_pattern,表達式成立時,觸發相應的actions執行。
① 表達式中可以使用變量(如字段變量$1,$2等)和/regexp/
② 布爾表達式中的操作符:
關係操作符: < > <= >= == !=
匹配操作符: value ~ /regexp/ 如果value匹配/regexp/,則返回真
value !~ /regexp/ 如果value不匹配/regexp/,則返回真
舉例: awk '$2 > 10 {print "ok"}' input_file
awk '$3 ~ /^d/ {print "ok"}' input_file
③ &&(與) 和 ||(或) 可以連接兩個/regexp/或者布爾表達式,構成混合表達式。!(非) 可以用於布爾表達式或者/regexp/之前。
舉例: awk '($1 < 10 ) && ($2 > 10) {print "ok"}' input_file
awk '/^d/ || /x$/ {print "ok"}' input_file
④ 其它表達式用作awk_script,如賦值表達式等
eg: awk '(tot+=$6); END{print "total points :" tot }' input_file // 分號不能省略
awk 'tot+=$6 {print $0} END{print "total points :" tot }' input_file // 與上面等效

5.actions
actions就是對awk讀取的記錄數據進行的操作。actions由一條或多條語句或者命令組成,語句、命令之間用分號(;)分隔。actions中還可以使用流程控制結構的語句。
1) awk的命令:
① print 參數列表 : print可以打印字符串(加雙引號)、變量和表達式,是awk最基本的命令。參數列表要用逗號(,)分隔,如果參數間用空格分隔,打印出時參數值之間不會有空格。
② printf ([格式控制符],參數) : 格式化打印命令(函數),語法與C語言的printf函數類似。
③ next : 強迫awk立刻停止處理當前的記錄,而開始讀取和處理下一條記錄。
④ nextfile : 強迫awk立刻停止處理當前的輸入文件而處理輸入文件列表中的下一個文件
⑤ exit : 使awk停止執行而跳出。如果有END 存在,awk會去執行END 的actions。

2) awk的語句: awk的語句主要是賦值語句,用來給變量賦值。
① 把直接值或一個變量值賦值給變量。如果直接值是字符串要加雙引號。
舉例: awk 'BEGIN {x=1 ; y=3 ; x=y ; print "x=" x " ; y=" y }'
② 把一個表達式的值賦值給變量。表達式一般是數值表達式,也可以是其它表達式。
數值表達式: num1 operator num2
operator可以是: +(加) -(減) *(乘) /(除) %(取模) ^(求冪)
當num1或者num2是字符串而是不是數字時,無論是否加有雙引號,awk都視其值爲0
條件選擇表達式: A?B:C (A爲布爾表達式,B和C可以是表達式或者直接值)
當布爾表達式A的值爲真時,整個表達式的值爲B,A的值爲假時,整個表達式的值爲C
舉例: awk 'BEGIN {x=3 ; x+=2 ; y=x+2 ; print "x=" x " ; y=" y }'
awk 'BEGIN {x=3 ; y=x>4?"ok":4 ; print "x=" x " ; y=" y }'
③ 爲了方便書寫,awk也支持C語言語法的賦值操作符: += -= *= /= %= ^= ++ --

3) 流程控制結構 (基本上是使用C語言的語法)
其中condition一般爲布爾表達式,body和else-body是awk語句塊。
① if (condition) {then-body} [else {else-body}]
② while (condition) {body}
③ do {body} while (condition)
④ for (initialization; condition; increment) {body}
與C語言的for結構的語法相同。
⑤ break : 跳出包含它的for、while、do-while 循環
⑥ continue : 跳過for、while、do-while循環的body的剩餘部分,而立刻進行下一次循環的執行。

6.awk的變量
在awk_script中的表達式中要經常使用變量。不要給變量加雙引號,那樣做,awk將視之爲字符串。awk的變量基本可以分爲兩類:
1) awk內部變量: awk的內部變量用於存儲awk運行時的各種參數,這些內部變量又可以分爲:
① 自動內部變量: 這些變量的值會隨着awk程序的運行而動態的變化,在awk_script中改變這些變量的值是沒有意義的(即不應該被賦值)。常見的有:
NF : 當前輸入字段的字段數
NR : 對當前輸入文件而言,已經被awk讀取過的記錄(行)的數目。
FNR : 已經被awk讀取過的記錄(行)的總數目。當輸入文件只有一個時,FNR和NR是一致的。
FILENAME : 當前輸入文件的文件名。
ARGC : 命令行參數個數。(不包括選項和awk_script,實際就是輸入文件的數目加1)
ARGIND : 當前被處理的文件在數組ARGV內的索引( 實際上ARGV[1]就是第一個輸入文件 )
舉例: awk '{print NR,NF,$0} END {print FILENAME}' input_file
② 字段變量($0 $1 $2 $3 ...): 當awk把當前輸入記錄分段時,會對這些字段變量賦值。和內部變量類似,在awk運行過程中字段變量的值是動態變化的。不同的是,修改這些字段變量的值是有意義的,被修改的字段值可以反映到awk的輸出中。
可以創建新的輸出字段,比如,當前輸入記錄被分割爲8個字段,這時可以通過對變量 $9 (或$9之後的字段變量)賦值而增加輸出字段,NR的值也將隨之變化。
字段變量支持變量名替換。
舉例: pwd |awk -F/ '{print $NF}' // print $NF 打印輸入記錄的最後一個字段
awk '{x=2;print $x}' input_file // 打印輸入記錄的第2個字段
③ 其它內部變量: 可以修改這些變量。常見的有:
FS : 輸入記錄的字段分隔符(默認是空格和製表符)
OFS : 輸出記錄的字段分隔符(默認是空格)
OFMT : 數字的輸出格式(默認是 %.6g)
RS : 輸入記錄間的分隔符(默認是NEWLINE)
ORS : 輸出記錄間的分隔符(默認是NEWLINE)
ARGV : 命令行參數數組
ENVIRON : 存儲系統當前環境變量值的數組,它的每個成員的索引就是一個環境變量名,而對應的值就是相應環境變量的值。可以通過給ENVIRON數組的成員賦值而改變環境變量的值,但是新值只在awk_script內有效。eg: ENVIRON["HISTSIZE"]=500
舉例: cat /etc/passwd | awk 'BEGIN { FS=":" } {print "User name: "$1,"UID: "$4}'

2) 自定義變量
1) 定義變量: varname=value (自定義變量不需先聲明後使用,賦值語句同時完成變量定義和初始化)
2) 在表達式中出現不帶雙引號的字符串都被視爲變量,如果之前未被賦值,默認值爲0或空字符串。
3) 向命令行awk程序傳遞變量的值:
① Usage: awk 'awk_script' awkvar1=value1 awkvar2=value2 .... input_file
eg: awk '{if ($5 < ARG) print $0 }' ARG=100 input_file
② awkvar可以是awk內置變量或自定義變量。
③ awkvar的值將在awk開始對輸入文件的第一條記錄應用awk_script前傳入。如果在awk_script中已經對某個變量賦值,那麼在命令行上傳人到該變量的值就會無效(實際上是awk_script中的賦值語句覆蓋了從命令行上傳入的值)。
④ 在awk腳本程序中不能直接使用shell的變量。通過使用下面的語法可達到這樣的效果。
awk 'awk_script' awkvar1=shellvar1 awkvar2=shellvar2 .... input_file
eg: awk '{if (v1 == "root") {print "User name is root!"}}' v1=$USER input_file
⑤ 可以向awk腳本傳遞變量的值,與上面的類似。
awk_script_file awkvar1=value1 awkvar2=value2 ... input_file

7.awk的內置函數
可以在awk_script的任何地方使用awk函數。和awk變量一樣,awk函數可以分爲內置函數和自定義函數。
1) 常見awk內置數值函數
int(x) : 求出x 的整數部份,朝向0 的方向做捨去。eg: int(3.9)是3,int(-3.9) 是-3。
sqrt(x) : 求出x 正的平方根值。eg: sqrt(4)=2
exp(x) : 求出x 的次方。eg: exp(2) 即是求e*e 。
log(x) : 求出x 的自然對數。
sin(x) : 求出x 的sine 值,x 是弳度量。
cos(x) : 求出x 的cosine 值,x 是弳度量。
atan2(y,x) : 求y/x 的arctangent 值,所求出的值其單位是弳度量。
rand() : 得到一個隨機數(平均分佈在0和1之間)。每次執行gawk,rand從相同的seed生成值。
srand(x) : 設定產生隨機數的seed爲x。如果在第二次運行awk程序時你設定相同的seed值,你將再度得到相同序列的隨機數。如果省略引數x,例如srand(),則當前日期時間會被當成seed。這個方法可使得隨機數值是真正不可預測的。
srand() : 其值是當次awk_script運行過程中前次srand(x)的設定的seed值x,。
2) 常見awk內置字符串函數
index(in, find) : 返回字符串in中字符串find第一次出現的位置(索引從1開始),如果在字串in中找不到字符串find,則返回值爲0。eg: print index("peanut","an") 會印出3。
length(s) : 求出字符串s的字符個數。eg: length("abcde") 是5。
match(s,r) : 返回模式字符串r在字符串s的第一次出現的位置,如果s不包含r,則返回值0。
sprintf(fmt,exp1,...) : 和printf類似印出,是sprintf不是打印而是返回經fmt格式化後的exp。
eg: sprintf("pi = %.2f (approx.)",22/7) 傳回的字串爲"pi = 3.14 (approx.)"
sub(p, r,t) : 在字符串t中尋找符合模式字符串p的最靠前最長的位置,並以字符串r代替最前的p。
eg: str = "water, water"sub(/at/, "ith",str) 結果字符串str 會變成"wither, water"
gsub(p, r, t) : gsub與sub類似。不過時在字符串t中以字符串r 代替所有的p。
eg: str="water, water" ; gsub(/at/, "ith",str) 結果字符串str會變成"wither,wither"
substr(str, st, len) : 傳回str的子字符串,其長度爲len字符,從str的第st個位置開始。如果len沒有出現,則傳回的子字符串是從第st個位置開始至結束。
eg: substr("washington",5,3) 傳回值爲"ing"
substr("washington",5) 傳回值爲"ington"
split(s,a,fs) : 在分隔符fs爲分隔符將字符串s分隔成一個awk數組a,並返回a的下標數。
eg: awk 'BEGIN{print split("123#456#789",myarray,"#")}' 將打印 3 。
tolower(str) : 將字符串str的大寫字母改爲小寫字母。
eg: tolower("MiXeD cAsE 123") 傳回值爲"mixed case 123"
toupper(str) : 將字符串string 的小寫字母改爲大寫字母。
eg: toupper("MiXeD cAsE 123")傳回值爲"MIXED CASE 123"
3) 常見awk內置系統函數
close(filename) : 將輸入或輸出的文件filename 關閉。
system(command) : 此函數允許調用操作系統的指令,執行完畢後將回到awk程序。
eg: awk 'BEGIN {system("ls")}'

8 自定義函數
複雜的awk常常可以使用自己定義的函數來簡化。調用自定義的函數與調用內置函數的方法一樣。
1) 自定義函數定義的格式: 自定義函數可以在awk程序的任何地方定義。
function fun_name (parameter_list) { // parameter_list是以逗號分隔的參數列表
body-of-function // 函數體,是awk語句塊
}
2) 舉例:
awk '{ print "sum =",SquareSum($1,$2) }
function SquareSum(x,y) { sum=x*x+y*y ; return sum } ' grade.txt

9.awk的數組
數組使用前,不必預先定義,也不必指定數組元素個數。
1) 訪問數組的元素。經常使用循環來訪問數組元素,下面是一種循環類型的基本結構:
for (element in array_name ) print array_name[element]
2) 舉例: awk 'BEGIN{print split("123#456#789",mya,"#") ; for (i in mya) { print mya[i] }} '

10.其他
1) 爲了避免碰到awk錯誤,可以總結出以下規律:
① 確保整個awk_script用單引號括起來。
② 確保awk_script內所有引號成對出現。
③ 確保用花括號括起動作語句,用圓括號括起條件語句。
④ 可能忘記使用花括號,也許你認爲沒有必要,但awk不這樣認爲,將按之解釋語法。
⑤ 如果使用字符串,一定要保證字符串被雙引號括起來(在模式中除外)。
2) 在awk中,設置有意義的域名是一種好習慣,在進行模式匹配或關係操作時更容易理解。一般的變量名設置方式爲name=$n。(這裏name爲調用的域變量名, n爲實際域號。)
3) 通常在BEGIN部分給一些變量賦值是很有益的,這樣可以在awk表達式進行改動時減少很多麻煩。
4) awk的基本功能是根據指定規則抽取輸入數據的部分內容並輸出,另一個重要的功能是對輸入數據進行分析運算得到新的數據並輸出,這是通過在 awk_script中對字段變量($1、$2、$3...)從新賦值或使用更大的字段變量$n(n大於當前記錄的NF)而實現的。
5) 使用字符串或正則表達式時,有時需要在輸出中加入一新行或查詢一元字符。這時就需要字符串屏蔽序列。awk中經常使用的屏蔽序列有:
/b 退格鍵 /t tab鍵 /f 走紙換頁 /ddd 八進制值 /n 新行 /r 回車鍵
/c 任意其他特殊字符。eg: //爲反斜線符號
6) awk的輸出函數printf,基本上和C語言的語法類似。
① 格式: printf ("輸出模板字符串",參數列表)
② 參數列表是以逗號分隔的列表,參數可以是變量、數字值或字符串。
③ 輸出模板字符串的字符串中必須包含格式控制符,有幾個參數就要求有幾個格式控制符。模板字符串中可以只有格式控制符而沒有其它字符。
④ 格式控制符: %[-][width][.prec]fmt
% : 標識一個格式控制符的開始,不可省略。
- : 表示參數輸出時左對齊,可省略。
width : 一個數字,表示參數輸出時佔用域的寬度,可省略。
.prec : prec是一個數值,表示最大字符串長度或小數點右邊的位數,可省略。
fmt : 一個小寫字母,表示輸出參數的數據類型,不可省略。
⑤ 常見的fmt : c ASCII字符
d 整數
e 浮點數,科學記數法
f 浮點數,如 123.44
g 由awk決定使用哪種浮點數轉換e或f
o 八進制數
s 字符串
x 十六進制數
⑥ 舉例: echo "65" | awk '{ printf ("%c/n",$0) }' // 將打印 A
awk 'BEGIN{printf "%.4f/n",999}' //將打印 999.0000
awk 'BEGIN{printf "2 number:%8.4f%8.2f",999,888}' // 將打印 2 number:999.0000 888.000 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章