Linux中有三種主要的文本處理工具,分別是grep,sed和awk,其中grep是文本過濾工具,sed是文本行編輯器,awk是報表生成器,今天咱們主要來探討awk。linux
awk有nawk,gawk等多種版本,如今默認linux系統下的awk是gawk,也就是咱們經常使用的awk,而在linux系統中gawk自己就是awk的連接文件,因此下文所說awk均爲gawk。shell
awk是一種用於處理文本的編程語言工具,在不少方面相似於shell編程語言,它支持條件判斷,數組,循環等各類編程語言中全部可使用的功能,因此在必定程度上咱們能夠把awk稱爲一種腳本語言解釋器,因爲awk在處理文本的時候一次讀取一行,並根據分隔符進行切片,因此awk能夠對文本中的特定片斷進行各類加工處理,例如計數,運算等編程
awk有三種運行方式,分別是如下三種數組
1.腳本編程語言
awk [options] ‘program’ var=value file編輯器
2.程序文件函數
awk [options] -f programfile var=value file工具
3.命令行spa
awk [options] 'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file命令行
其中的[options]:
-F 指明輸入時用到的字段分隔符
-v var=value: 自定義變量賦值
awk的前兩種運行方式直接調用文件或腳本,很少作解釋,如下重點討論awk的命令行用法
awk的命令行用法中,其格式由[options],BEGIN,pattern和END組成,其中[options]主要用於定義分隔符和定義變量,BEGIN是第一步僅且只執行一次的動做能夠不寫,pattern部分決定定動做語句什麼時候觸發及觸發事件,以及觸發什麼事件,END是最後一步僅且只執行一次的動做,也可不寫。
第一步:執行BEGIN{action;… }語句塊中的語句
第二步:從文件或標準輸入(stdin)讀取一行,而後執行pattern{ action;… }語句塊,它逐行掃描文件,從第一行到最後一行重複這個過程,直到文件所有被讀取完畢。
第三步:當讀至輸入流末尾時,執行END{action;…}語句塊
BEGIN語句塊在awk開始從輸入流中讀取行以前被執行,這是一個可選的語句塊,好比變量初始化、打印輸出表格的表頭等語句一般能夠寫在BEGIN語句塊中
END語句塊在awk從輸入流中讀取完全部的行以後即被執行,好比打印全部行的分析結果這類信息彙總都是在END語句塊中完成,它也是一個可選語句塊
pattern語句塊中的通用命令是最重要的部分,也是可選的。若是沒有提供pattern語句塊,則默認執行{ print },即打印每個讀取到的行,awk讀取的每一行都會執行該語句塊
awk執行時,由分隔符分隔的字段(域)標記$1,$2..$n稱爲域標識
$0爲全部域,注意:和shell中變量$符含義不一樣
文件的每一行稱爲記錄
省略action,則默認執行 print $0 的操做,也就是打印整個記錄
awk中變量分爲內置變量和自定義變量,自定義變量顧名思義就是咱們本身定義的變量,而內置變量則是awk爲方便咱們的使用爲咱們提早準備號的變量,在定義變量時,建議在[options]部分定義內置變量
FS:輸入字段分隔符,默認爲空白字符
OFS:輸出字段分隔符,默認爲空白字符
RS:輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效
ORS:輸出記錄分隔符,輸出時用指定符號代替換行符
NF:字段數量
NR:行號
FNR:各文件分別計數,行號
FILENAME:當前文件名
ARGC:命令行參數的個數
ARGV:數組,保存的是命令行所給定的各參數
在awk中定義自定義變量時若在[options]部分則直接用-v var=value(-v a=123)這樣的方式定義便可,若在program中定義,需用「;」隔開,因爲當value爲數值時能夠直接定義但value爲帶空格的字符串時沒法識別因此建議在定義變量時用引號將value引發
print格式: print item1, item2, ...
要點:
(1) 逗號分隔符
(2) 輸出的各item能夠字符串,也能夠是數值;當前記錄的字段、變量或awk的表達式
(3) 如省略item,至關於print $0
示例:
awk ‘{print "hello,awk"}'
awk –F: ‘{print}' /etc/passwd
awk –F: ‘{print 「wang」}’ /etc/passwd
按照格式輸出,書寫時先寫目標格式,再在後面補上內容
printf格式:printf 「FORMAT」, item1, item2, ...
要點:
(1) 因爲printf是格式化輸出因此必須指定FORMAT
(2) 不會自動換行,須要顯式給出換行控制符,\n
(3) FORMAT中須要分別爲後面每一個item指定格式符
格式符:與item一一對應
%c: 顯示字符的ASCII碼
%d, %i: 顯示十進制整數
%e, %E:顯示科學計數法數值
%f:顯示爲浮點數
%g, %G:以科學計數法或浮點形式顯示數值
%s:顯示字符串
%u:無符號整數
%%: 顯示%自身
修飾符:
#[.#]:第一個數字控制顯示的寬度;第二個#表示小數點後精度,%3.1f 表示一個三位的一位小數的浮點數
-: 左對齊(默認右對齊) %-15s 表示這一部分左對齊並去字符寬度爲15,不足則空格補齊
+:顯示數值的正負符號 %+d
示例:
awk -F: ‘{printf "%s",$1}’ /etc/passwd
awk -F: ‘{printf "Username: %s\n",$1}’ /etc/passwd
awk -F: ‘{printf "Username: %-15s,UID:%d\n",$1,$3}’ /etc/passwd
awk中支持各類操做符
算術操做符:
x+y, x
-y, x*y, x/y, x^y, x%y
-x: 轉換爲負數
+x: 轉換爲數值
賦值操做符:
=, +=,
-=, *=, /=, %=, ^=
++, --
邏輯操做符:與&&,或||,非!
比較操做符:
==, !=, >, >=, <, <=
模式匹配符:
~:左邊是否和右邊匹配(!~:是否不匹配)其中右邊要匹配的部分要用「」或者//括起來
awk–F: ‘$0 ~ /root/{print $1}’ /etc/passwd
awk ‘$0~「^root"' /etc/passwd
awk ‘$0 !~ /root/’ /etc/passwd
awk有如下幾種經常使用action
(1) Expressions:算術,比較表達式等
(2) Control statements:if, while等
(3) Compound statements:組合語句
(4) input statements
(5) output statements:print等
因爲其餘的action在上面都有介紹因此這裏主要講述控制語句而組合語句則是多種action的組合
if語句經常使用於對awk取得的某個字段進行條件判斷
格式:if(condition1){statement1}else if(condition2){statement2}
else{statement3}
例如:
用awk讀取/etc/passwd 輸出系統用戶和普通用戶
awk -F: ‘{if($3>=1000) {printf "Common user: %s\n",$1} else {printf
"root or Sysuser: %s\n",$1}}' /etc/passwd
while經常使用於對同行內多個字段逐一處理和對數組個元素逐一處理
格式:while(condition){statement;…}
例如:
用awk讀取/etc/grub2.cfg 輸出以任意空格加linux16做爲開頭的行的全部字段的長度
其中length()是一個awk的內置函數
awk ‘/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i); i++}}’ /etc/grub2.cfg
for語句功能和while基本相同,一樣可用於遍歷數組
格式:for(variable assignment;condition;iteration process) {for-body}
例如:
用for代替上面的while輸出以任意空格加linux16做爲開頭的行的全部字段的長度
awk ‘/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
awk中的break和continue同shell腳本中的功能同樣,break跳出當前層的循環,continue跳過本次循環直接進入下一次,固然能夠在break和continue跟上數字以表示跳出的循環個數,默認爲1.而next則是跳出awk自己的循環,即直接進入下一行的循環。
例如:
awk '{for (i=1;i<3;i++){if (i==2){break}else{print i}}}' /etc/passwd這個循環中break直接跳出當前的for循環直接進入下一行的循環,若是把break換成continue則是跳出本次循環,直接進入i=3時的循環而後才進入下一行的循環。若是把break換成next則是直接進入下一行的循環,因爲這個awk語句中除了awk自己的循環只有一層循環因此在這條語句中break和next做用相同。
awk中數組一般是以字符串爲下標的,其他和shell腳本中的數組基本相同
awk的數組通常寫在pattern中,以遍歷整個文件,而後在END中經過循環輸出咱們的數組
例如:
計算/etc/passwd中各類默認shell的個數,其中默認shell是這個文件每行的第七個域,在pattern部分直接以默認shell爲數組下表,在awk循環遍歷整個文件時,每遇到一種shell就在line數組中建立一個對應的下標,並讓這個下標對應的值加一,以後每遇到一次都加一,而後在END部分經過for循環遍歷輸出每一個下標及其對應的值,也就是出現的次數
awk -F: ‘{line[$7]++}END{for(i in line){print i,line[i]}}' /etc/passwd