awk學習精要

來源:互聯網
上載者:User

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 awk指令檔 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) Regex用作awk_pattern: /regexp/
    ① awk中Regex匹配操作中經常用到的字元: / ^ $ . [] | () * // 通用的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或Null 字元串。
    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) 使用字串或Regex時,有時需要在輸出中加入一新行或查詢一元字元。這時就需要字串屏蔽序列。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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.