linux 文本三劍客之awk
awk簡介
awk同sed、grep被稱為linux文本處理三劍客,都起源於行編輯器ed。awk繼承了行編輯器的特點,循環的讀取文本的每一行(或者是分隔符分割的每一段文本)直至文本結束,但是awk加入了段分割符的概念.將每次讀入的行進行再次分割.awk每次讀取的行都只是未經過awk語句處理的對象。或讀取行後會根據段分割符在將行分成多個對象。結構近似數組,然後進行指定語句的操作。作為一款報表生成器,作用是對對文本內容進行各種排版,進而格式化顯示。
awk有自己的語法,可以說是一款獨立的編程語言。 它對命令的處理可以稱為命令的解釋,或腳本語言的解釋 awk的語句書寫格式,屬於模塊化風格,特別是if,else語句表現的特別明顯有點類似於bash中的匿名函數。每個語句塊必須使用{}進行約束。
本文介紹了awk的常用用法及講解並添加示例以便加深理解,結尾準備了實戰練習以加強鞏固,請讀者自行按需閱讀,如有紕漏望請指出。
1、awk基本執行流程
2、awk基本格式
3、printf 用法及格式符、修飾符
4、awk中的控制語句
5、awk中的函數、變量及操作符
6、實戰練習
1、awk基本執行流程
①執行BEGIN語句塊中的內容,語句為可選語句.多用於執行變量的初始化,報表的頭輸出.
②從標準輸入或文件中讀取行分割符(-F定義的字符)分割的行進入內存,進行語句之前的條件匹配,在沒有條件時默認為符合執行條件.符合條件執行,不符合條件則嘗試匹配下一個語句之前的條件.直至所有條件匹配全部完成.當語句為空時默認執行{print $0}
③繼續讀取下一行,直至末尾
④執行END定義的語句內容,同樣也為可選語句.多用於報表的統計信息輸出.
2、awk基本格式及匹配條件
基本格式: awk選項 條件 語句 文件
選項:
-f 從文件中讀取處理命令 -F 指明行的段分隔符;默認為空白字符(一個或多個) -v 自定義變量
條件:
條件為執行條件後的語句的要求。符合條件才可執行語句,條件即為對語句的判斷,可以使用正則匹配,基於正則的模式定界,字符串比較,可以使用算數條件表達式,也可以是BEGIN,END特殊條件。
算數條件表達式,最終返回運算結果,當運算結果為0時,語句不執行。當語句為空時,默認執行{print
例:正則_匹配正則匹配的每一行
awk ‘/^UUID/{print $1}‘/etc/fstab 匹配以UUID為開始的行,並執行{}中的語句。print $1 awk ‘!/^UUID/{print $1}‘ /etc/fstab 匹配以非UUID為開始的行,執行{}中的語句 。print $1
例:算數計算_條件為真該行才會被處理 ,條件 為假則不處理 。
awp -F: ‘$3>=1000{print $1,$3}‘ /etc/passwd awp -F: ‘!$3>=1000{print $1,$3}‘ /etc/passwd awk -F:‘(NR>=2&&NR<=10){print $1}‘
例:字符串比較_比較結果為真進入循環
awk -F:‘$NF="/bin/bash"{print $1,$NF}‘ /bin/passwd awk -F:‘$NF~/bash$/{print $1,$NF}‘ /bin/passwd awk -F: ‘! ($NF=="/bin/bash")‘ /etc/passwd
例:行範圍_範圍內的行做處理 ,只支持模式定界(類似sed中的10,20地址定界不支持)
awk -F:‘/^root/,/^myuser/{print $1}‘
例:特殊條件_BEGIN/END
BEGIN:在開始之前顯示一次 END:在文本處理完成 ,命令未完成時,執行一次 awk ‘BEGIN{print "usernameID\n------------"}{printf "%10s:%-s" $1,$3}END{print "=========\n"}‘
例:特殊條件0,空。
awk -v aa="" ‘aa‘ /etc/passwd 變量aa的值為空 ,(語句為空執行默認語句)。但是條件為空,不執行默認語句。 awk -v aa=" " ‘aa‘ /etc/passwd 變量aa的值為‘ ’空格不為空執行默認語句 awk -v aa="0" ‘aa‘ /etc/passwd 變量aa的值為0,條件為最終值為0,默認語句不執行。 awk ‘!arr[$0]++’ dupfile 以$0為下標建立數組,只打印文件不重復的行 awk -v aa=0 ‘aa++‘ /etc/passwd aa初始值為0,第一條語句條件為a++,首先返回a的值在進行自加運算。所以打印第一行外所有行。awk中 默認對非關鍵字變量都賦值0,這個例子也可以寫成 awk ‘aa++‘ /etc/passwd 打印效果相同。
3、printf 用法及格式符、修飾符
print類似bash中的echo打印給定字符並自動添加換行這裏不多說,printf對輸出格式可以自定義,用法需要大家註意。
語法:printf FORMAT,item1,item2,...
①必須提供FORMAT
②printf不會自動換行,若想換行需加換行符:\n
③FORMAT中需要依次分別為後面每一個item指定一個格式符,否則item不顯示。
格式符:
%c : 顯示字符的ascii碼 %d或i: 顯示十進制整數 %e或%E:科學記數法顯示數值 %f: 顯示浮點數 %s: 顯示字符串 %% : 顯示%自身 %g或%G:以科學計算法或浮點數格式顯示數值 %u: 無符號的整數
修飾符:
#[.#]:左邊#用於顯示寬度 右邊的#表示小數點後的精度 - : 左對齊,默認右對齊。 + : 顯示數字的正負符號
4、awk中的控制語句
(1)、條件表達式
格式:條件?條件為真的語句:條件為假的語句
例:
awk -F:‘{$3>=500?usertype="common":usertype="sysadmin";printf "%15s:%-s\n",$1,usertype}’ /etc/passwd
(2)、if-else:
格式:
if(條件){語句} if(條件){語句} else {語句}
例:
awk -F: ‘{if($3>1000) print $1,$3}‘ /etc/passwd awk -F: ‘{if($3>1000){printf "普通用戶:%s",$1} else {printf "系統用戶:%s",$1}}‘
(3)、while循環:
while (條件) {語句} 條件為真進入循環 ,條件為假退出循環。
例:
awk ‘/^[[:space:]]*linux/{i=1;while(i<NF){print $i,length($i);i++}}‘ /etc/grub2.cfg awk ‘/^[[:space:]]*linux/{i=1;while(i<NF){if(length($i)>7){print $i,length($i)};i++}}‘ /etc/grub2.cfg
(4)、do-while循環:
do{語句} while(條件)
首先執行do後面的語句。然後對while中的條件進行判斷。條件符合繼續執行do後的語句。至少執行一次循環。
(5)、for循環:
語法:for(expr1;expr2;expr3){statements}
例:
awk /[[:space:]]*linux/{for(i=1;i<=NF;i++){print $i,length($i)}} /etc/grub2.cfg
for可以實現遍歷數組元素 :
格式 :for (i in 數組名稱)遍歷時 i被賦值的是每個索引
5、awk中的函數、變量及操作符
函數:分為內建函數和自定義函數
內建函數:
數值處理:rand()與srand() 組合使用返回一個0至1之間的隨機數。
字符串處理:
length([s]):統計指定字符串的長度,並返回。
sub(r,s[,t]):處理字符串t(可以是單純的字符串,變量,位置引用),對t進行模式匹配,模式定義在r中,將模式r所匹配的內容替換成s中的內容,但是只進行1次替換
例:echo "2008:08:08:08 08:08:08:08" |awk ‘sub(/:/,"-",$0)‘
gsub (r,s,[t]):處理字符串t(可以是單純的字符串,變量,位置引用),對t進行模式匹配,模式定義在r中,將模式r所匹配的內容替換成s中的內容,對於待處理的字符串t進行全局替換。
例:echo "[email protected]%9&Bdh7dq+YVixp3vpw"|awk ‘{gsub(/[^0-9]/,"",$0);print $0}‘
split(a,array,[r]):以r為分隔符,分割字符串a,並將分割後的字符串分別存入數組,數組的下標從1開始,第一個索引為1,第二個索引為2.
例:netstat -tan |awk ‘/^tcp/{split($4,ip,":");a[ip[1]]++}END{for(i in a){print i,a[ip[1]]}}‘
int:將指定的內容轉換為整數類型
自定義函數
格式:
function 函數名稱 (參數1 ,參數2 。。。){ 語句1 語句2 return 數值 }
例:
#cat fun.awk function max(v1,v2) { v1>v2?var=v1:var=v2 return var } BEGIN{a=3;b=2;print max(a,b)}
變量:分為內建變量和自定義變量
內建變量:
FS:輸入的字段分割符,默認為空白字符
OFS:輸出的字段分隔符,默認也為空白字符。
RS:輸入時指明的行分割符,默認就是換行符,
ORS:輸出時的行分隔符,默認為換行符
NF :行中的字段數量
NR :行計數器 ,如果跟了多個文件編號會連續
FNR : 行數,各文件單獨計數 。
FILENAME : 當前的文件名
ARGC :命令行中的參數個數(awk也算一個參數)
ARGV :命令行中的參數 ,ARGV為數組,參數為命令自身及後跟隨的文件 ,語句不計入參數
自定義的變量
-v var=value
在語句中直接定義,多條與語句之間使用 ;分隔,每定義一個變量需要一個-v。
操作符
算數操作符 :實現算數運算x+y x-y x*y x/y x^y x%y
-x :將x 轉化為負數
+x :將字符串x 轉化為 數值
賦值操作符 :通常為變量賦值
= += -= *= /= ^= %=
++ --
比較操作符:> >= < <= != ==
模式匹配操作符:根據右側的模式進行匹配操作
~ : 是否由右側模式匹配
!~:是否由右側模式不匹配
邏輯操作符 :進行邏輯的運算與bash腳本中用法不同
&& :並且
|| :或者
!:非
6、awk實戰練習
(1)、統計/etc/fstab文件中每個文件系統類型出現的次數
awk ‘!/^#/{arr[$3]++}END{for(i in arr){print i,arr[i]}}‘ /etc/fstab
(2)、提取出字符串[email protected]%9&Bdh7dq+YVixp3vpw中的所有數字
echo "[email protected]%9&Bdh7dq+YVixp3vpw"|awk ‘gsub(/[^0-9]/,"",$0)‘
(3)、統計/etc/fstab文件中每個單詞出現的次數
awk ‘{i=1;while(i<=NF){word[$i]++;i++}}END{for(num in word){print num,word[num]}}‘ /etc/fstab
(4)、計算男生女生的總成績,平均成績
#cat 1.txt mage 100 male wang 80 male zhang 70 female li 100 female #awk ‘{if($3=="male"){msum+=$2;mnum++}else{fesum+=$2;fenum++}}END{printf "%-5d %-.2f\n%-5d %-.2f\n",msum,msum/mnum,fesum,fesum/fenum}‘ 1
本文出自 “linux運維” 博客,請務必保留此出處http://arm2012.blog.51cto.com/2418467/1963105
linux 文本三劍客之awk