看示例學awk
本文詳細介紹了awk語法結構、關鍵字、運算子、內建變數、陣列、正規表示式元字元、內建函式、算術函式、條件語句和迴圈等方面的內容,並透過豐富的示例來幫助大家熟悉使用awk。
介紹
awk是一個強大的文字分析工具。
awk其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。實際上 awk 的確擁有自己的語言: awk 程式設計語言 , 三位建立者已將它正式定義為“樣式掃描和處理語言”。它允許您建立簡短的程式,這些程式讀取輸入檔案、為資料排序、處理資料、對輸入執行計算以及生成報表,還有無數其他的功能。
語法結構
awk option scrips file
option
-F 指定分隔符,而不以預設的空白(空格符或者製表符)
-v 指定變數
-f 指定指令碼的檔名,即將指令碼放入一個檔案當中,避免 awk 書寫太長,影響視覺,和重複編寫
關鍵字
BEGIN 關鍵字會執行一次指定的指令碼段
END 關鍵字定義的指令碼段,在所有操作完成之後
處理資料的指令碼段在第二個程式中定義
測試檔案內容
程式碼裡井號開頭部分的代表輸出內容(輸出不包含井號),下同
cat mi_info # mi6-1 5.15" 835 6G 64G 3350mAh 2499 # mi6-2 5.15" 835 6G 128G 3350mAh 2899 # minote3-1 5.5" 660 6G 64G 3500mAh 2499 # minote3-2 5.5" 660 6G 128G 3500mAh 2899 # mix2-1 5.99" 835 6G 64G 3400mAh 3299 # mix2-2 5.99" 835 6G 128G 3400mAh 3599 # mix2-3 5.99" 835 6G 256G 3400mAh 3999
初級示例
# 預設的模式匹配中就已經包含了 if 的意思了 awk '/2499/' mi_info # mi6-1 5.15" 835 6G 64G 3350mAh 2499 # minote3-1 5.5" 660 6G 64G 3500mAh 2499 awk '$5=="256G"' mi_info # mix2-3 5.99" 835 6G 256G 3400mAh 3999 awk '$1 ~ "note"{print}' mi_info # minote3-1 5.5" 660 6G 64G 3500mAh 2499 # minote3-2 5.5" 660 6G 128G 3500mAh 2899 awk '$0 ~ /note/{print $1, "MEMSIZE->", $3, "Price->", $NF}' mi_info # minote3-1 MEMSIZE-> 6G Price-> 2499 # minote3-2 MEMSIZE-> 6G Price-> 2899 ## -f 示例 # cat awkfile /note/{ test="price is" print $1, test, $NF } awk -f awkfile mi_info # minote3-1 price is 2499 # minote3-2 price is 2899 ## -v 示例 awk -v test="price is" '/note/{ print $1, test, $NF}' mi_info # minote3-1 price is 2499 # minote3-2 price is 2899運算子(優先順序由大到小排列)
++ -- 增加與減少(前置或後置)
^ ** 指數(右結合性)
! + - 非、一元加號、一元減號
* / % 乘、除、餘數
+ - 加、減
< <= == != > >= 比較
&& 邏輯AND( 簡寫)
|| 邏輯OR( 簡寫)
?: 三元條件式
= += -= *= /= %= ^= **= 賦值( 右結合性)
內建變數
$ 後面跟數字,表示獲取指定列的域,0 代表取整條記錄
ARGC 命令列引數個數
ARGV 命令列引數構成胡陣列
FILENAME 當前輸入檔案的檔名
FS 設定輸入域分隔符,等價於命令列 -F選項
OFS 輸出域分隔符
RS 控制記錄分隔符
ORS 輸出記錄分隔符
NF 瀏覽記錄的域的個數
NR 已讀的記錄數
FNR 與NR功用類似,不同的是awk每開啟一個新檔案,FNR便從0重新累計
IGNORECASE 是否忽略大小寫
記錄 預設指的是每行,因為記錄分隔符(RS)是換行符
域 預設指的是每個單詞,因為域分隔符(FS)是空格
awk 透過內建變數 ARGC ( 引數計數 ) 與 ARGV ( 引數向量,或引數值 ) ,讓命令列引數可用。
高階示例
cat showargs.awk BEGIN { print "ARGC= ", ARGC
for (k=0; k<ARGC; k++) { print "ARGV["k"]=["ARGV[k]"]" } } awk -f showargs.awk mi_info # ARGC= 2# ARGV[0]=[awk] # ARGV[1]=[mi_info] ## 求和 awk '{sum+=$NF} END {print "Sum = ", sum}' mi_info # Sum = 21693
## 求平均 awk '{sum+=$NF} END {print "Average = ", sum/NR}' mi_info # Average = 3099
## 求最大值 awk 'BEGIN {max = 0} {if ($NF>max) max=$NF fi} END {print "Max=", max}' mi_info # Max= 3999
## 求最小值(min的初始值設定一個超大數即可) awk 'BEGIN {min = 1999999} {if ($NF<min) min=$NF fi} END {print "Min=", min}' mi_info # Min= 2499
# 求訪問次數的Top 10 Resource,可以根據此進行最佳化 cat logs/`date +%u`.log | grep -v '172.16' |grep -v '127.0.0.1' \ | awk '{ if(index($1,"219.141.246")!=0) print $2; else print $1 }' \ | sort | uniq -c | sort -n | tail -n 10
# awk的範圍模式也是封閉範圍。 # 在所有記錄中他們會順序進行多次匹配,第一次匹配完後還可以進行下面接下來的第二次、第三次可能的匹配範圍。 # 如果開頭匹配到了,但是沒有結尾的話,會把整個檔案記錄的末尾當作是這次匹配的結尾作為範圍 awk '/mi6/,/note/ {print NR, $1, $NF}' mi_info # 1 mi6-1 2499
# 2 mi6-2 2899
# 3 minote3-1 2499
# 忽略大小寫 awk '{IGNORECASE=1}; $1~"MI" {print NR,$0}' mi_info # "所有資訊"
# 每 5 行合併為 1 行 BEGIN { a = 0; s = ""; } { a += 1; s = s" | "$0 if (a % 5 == 0) { print s; s = ""; } } END { print s } awk 'BEGIN{a="100"; b="10test10"; print (a+b+0);}'
# 110
# 只需要將變數透過 "+" 連線運算。自動強制將字串轉為整型。 # 非數字變成 0,發現第一個非數字字元,後面自動忽略。 awk 'BEGIN{a=100;b=100;c=(a""b);print c}'
# 100100
# 只需要將變數與 "" 符號連線起來運算即可。 awk 'BEGIN{a="a";b="b";c=(a+b);print c}'
# 0
# 字串連線操作通"二","+"號運算子。模式強制將左右2邊的值轉為 數字型別。然後進行操作。
陣列
## 陣列示例 awk 'BEGIN{x=0;i=0;} \ {name[x++]=$1;} \ END { for(;i<NR;i++){ print "name["i"] is",name[i]} }' mi_info # name[0] is mi6-1
# name[1] is mi6-2
# name[2] is minote3-1
# name[3] is minote3-2
# name[4] is mix2-1
# name[5] is mix2-2
# name[6] is mix2-3
正規表示式元字元
^ 行首定位符
$ 行尾定位符
. 匹配除換行之外的單個字元
\* 匹配0個或者多個前導字元(這裡是前導字元0或者多個,任意一個或多個字元,使用 .* )
+ 匹配一個或者多個前導字元
? 匹配0個或者1個前導字元
[] 指定字元中的任意一個字元,比如[Ll] [a-z]
[^] 上面一樣,不匹配的字元
AA|BB 匹配AA或者BB
(AB)+ 匹配一個或者多個AB組合,比如AB,ABAB,ABABAB...
\* 匹配*本身
& 儲存查詢匹配到的串,可以用在後面的替換中 s/love/**&**/
內建函式
sub(/reg/,替換串[,目標串])
gsub(/reg/,替換串[,目標串])
index(str,sub_str) 返回sub_str第一次在str中出現的位置(偏移量從1開始)
length(str) 返回字串的字元個數
substr(str,start_pos[,length]) 返回子串,如果沒有length,就到串的末尾
match(str,/reg/) 返回正則匹配在字串中的位置,同時設定RSTART和RLENGTH的值
split(str,arr_name[,split_sig])
算術函式
atan2(x,y)
cos(x)
exp(x)
log(x)
sin(x)
sqrt(x)
int(x)直接捨去小數,保留整數部分
rand() 產生隨機數(0~1) srand(x) 初始化隨機數種子
預設情況下每次呼叫rand(),結果都會產生相同的隨機數,這時候需要呼叫srand()重新產生一個種子,後面的隨機數才不同
## 函式示例 awk 'BEGIN{ print rand(),rand(),srand(),rand(),rand();}'
# 0.237788 0.291066 1 0.215969 0.629868
awk 'BEGIN{ print rand(),rand(),srand(),rand(),rand();}'
# 0.237788 0.291066 1 0.556348 0.749557
awk 'BEGIN{ print rand(),rand(),srand(),rand(),rand();}'
# 0.237788 0.291066 1 0.0931369 0.835396
條件語句和迴圈
## 語句和迴圈示例 (a) if
# 在條件模式中,if是隱含的模式了,而條件語句if也可以按照需要直接宣告出來的句式類似於
if () {} else if () {} else {} awk '{ if( $1 ~ /note/) { print "note related."} else if ( $1 ~ /mix/ ) { print "mix related."} else { print "other ..."} }' mi_info # other ... # other ... # note related. # note related. # mix related. # mix related. # mix related. (b) while
# 句法
while () {} awk 'BEGIN { i = 0; count = 0; } { while ( i < NR ) { i ++; if ( $1 ~ /note/ ) { count++; print NR, $1,$4,$5 } } } END { print "Count:",count }' mi_info # 3 minote3-1 6G 64G # 4 minote3-2 6G 128G # Count: 2
(c) for
# 普通for迴圈,句法
for( ; ; ){} awk 'BEGIN { i = 0;} { for(;i<NR;i++) { if( $1 ~ /note/ ){ print NR,$1,$4,$5,"~~" } }}' mi_info # 3 minote3-1 6G 64G ~~ # 4 minote3-2 6G 128G ~~ (d) break continue
# 同C/C++語言一樣,是作用於跳出迴圈體和跳出本次迴圈的關鍵字。 ### 程式控制語句 (a) next # 從檔案中讀取下一行輸入,然後從awk指令碼頂部開始重新執行。同continue效果也有點相似,只不過這裡是作用於awk工具在對每行操作的自動“迴圈”中的
(b) exit # 中斷記錄的處理,但是不能夠跳過END語句塊。exit可以帶一個範圍為0~255的退出引數,約定0表示成功,這個退出引數實際就傳遞給了$?表示執行的結果 awk '{ if ( $1 ~ /note/ ) { print NR,$1,$7,"skip"; next; } if ( $1 ~ /mix/ ) { print NR,$1,$7,"exit will"; exit 3; } print NR,$1,$7,"after if..."; } END { print "Fininal should be called here..." }' mi_info # 1 mi6-1 2499 after if... # 2 mi6-2 2899 after if... # 3 minote3-1 2499 skip # 4 minote3-2 2899 skip # 5 mix2-1 3299 exit will # Fininal should be called here... echo $? # 3
系統互動
## (a) 支援 > >> 重定向符號使用的時候作為檔名引數需要使用 "" 括起來,getline可以用於輸入重定向來獲得輸入資訊 awk 'BEGIN { "date" | getline date; print "The date is",date > "date.file"}' cat date.file # The date is Wed Dec 28 18:43:39 HKT 2016 ## (b) 管道 | awk '/note/ { print $0 | "grep 2499" }' mi_info # minote3-1 5.5" 660 6G 64G 3500mAh 2499 ## (c) system 函式。可以進行系統命令呼叫 awk 'BEGIN { system("whoami") }' # root ## (d) printf 格式化輸出資訊,跟C語言的類似 awk 'BEGIN { printf "Hello, %s, you are %d years old.\n","Nicol TAO","23"}' # Hello, Nicol TAO, you are 23 years old.
總結
最後總結一下awk使用經驗:
如果處理邏輯複雜,就將程式碼寫進檔案裡,再透過 -f 引用;這樣可防止敲錯程式碼。
靈活呼叫系統命令,內建變數,使程式碼更簡潔。
處理大檔案時,多稽核最佳化邏輯程式碼,可有效提高執行效率。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559359/viewspace-2285016/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- awk 學習總結
- [20200208]awk學習例子.txt
- awk
- grep 、awk
- awk例子
- gsub in awk
- awk命令
- linux之 awkLinux
- [Bash] awk command
- Linux-(awk)Linux
- linux之awkLinux
- awk常用案例
- 『忘了再學』Shell基礎 — 29、AWK內建變數變數
- JS原生示例 案例 學習JS
- 通過示例學習PYTORCHPyTorch
- awk的總結
- awk 入門教程
- 三劍客——AWK
- linux的awk命令Linux
- Solaris awk: syntax error near line 1 awk: bailing out near line 1ErrorAI
- 透過編寫“猜數字”遊戲來學習 Awk遊戲
- 看圖學HTTPSHTTP
- Linux:“awk”命令的妙用Linux
- awk的強大操作
- 【Linux篇】--awk的使用Linux
- Awk常用用法整理
- awk中使用迴圈
- awk命令使用例項
- AWK 陣列介紹陣列
- linux awk使用方法Linux
- AWK高階應用
- Linux awk使用案例教程Linux
- Linux awk 命令詳解Linux
- sed awk 編輯器
- 一分鐘學awk夠用(產品經理都懂了)
- 機器學習與比特幣示例機器學習比特幣
- SQL 行轉列 PIVOT 學習示例SQL
- 給初學者的 fc 示例教程