1. 程式人生 > >文本三劍客之awk

文本三劍客之awk

urn 邏輯或 mark bre 取出 整數 空格 讀取文件 val

awk是一種報告生成器,能夠格式化輸出文本,有著多種版本,我們主要使用的是GNU awk,通常也稱之為gawk,可以進行模式掃描和處理的語言。

1.awk語法

awk的基本語法如下:

awk [options] ‘program’ var=value file…
awk [options] -f programfile var=value file…
awk [options]  ‘BEGIN{ action;… } pattern{ action;… } END{ action;… }‘  file

第一句的語法是awk加上選項,加上程序部分,加上變量,最後是要操作的文件路徑
第二句的語法是awk加上選項,接一個-f,後面是程序部分,不過此處的程序不在是一串代碼,而是一個文件,這個文件的內容是程序代碼,後面是變量和要操作的文件名

第三句的代碼是awk加上選項,後面接的是程序部分,它由BEGIN,pattern,END三部分中的部分組成,後面接的是要操作的文件名。
程序代碼部分是需要用單引號或者雙引號引起來,這樣能夠將awk的代碼和shell語言分隔開。
BEGIN部分
BEGIN部分代碼是在程序執行過程中最先被執行的部分,是可以選擇執行的,他執行是在讀文件之前,所以單獨的一個BEGIN是不需要文件的,例如:

awk ‘BEGIN{print“hello world”}’

執行結果如下:
技術分享圖片
BEGIN主要用來打印生成表的表頭等其他語句。
pattern部分
pattern是對文件處理的部分,他會按照記錄一個一個的掃描,知道所以的記錄都被掃描過結束,pattern是程序中最重要的部分,他也是可以選擇執行的,如果沒有pattern部分,則默認執行{print},即打印文件中的每一行,讀取文件中的每一行都會執行該語句,例如:

awk ‘1‘ /etc/fstab

執行結果如下:
技術分享圖片
END部分
END部分語句是在讀至輸入流末尾時執行的語句,這部分代碼也是可以選擇執行的,比如打印所有行的分析結果這類的信息匯總,例如

awk ‘{print}END{print "hello world"}‘ /etc/fstab

執行結果如下:
技術分享圖片

2.分割符、域和記錄

awk執行時,由分隔符分隔的字段(域)標記$1,$2..$n稱為域標識,我們可以選擇打印輸出這些域的內容。例如

awk -F‘ ‘ ‘{print $1,$3}‘ /etc/fstab

執行結果如下:
技術分享圖片
$0為所有域,例如:

awk -F‘ ‘ ‘{print $0}‘ /etc/fstab

執行結果如下:

技術分享圖片
文件按記錄來進行執行awk操作,在shell中每一行稱為一條記錄,awk中可以指定特定的文件記錄分割符。在shell中$是引用變量,而在awk中$的作用是引用記錄中的第幾個片段。
省略action,則默認執行 print $0 的操作,如果程序代碼中的內容為空或0,是什麽都不會執行的,因為空也是0,如果是非0,就默認執行{print},例如:

awk -F‘ ‘ ‘0‘ /etc/fstab

執行結果如下:
技術分享圖片
-F選項可以指定記錄中域的分割符,可以是任何東西。

3.awk內置變量

1.FS:輸入字段分隔符,默認為空白字符,例如:

awk ‘{print $1"  "$3}‘ /etc/fstab

執行結果如下:
技術分享圖片
我們設置輸入字段分隔符為/,例如:

awk -v FS=‘/‘ ‘{print $1"  "$3}‘ /etc/fstab

執行結果如下:
技術分享圖片
因為FS是內置變量,所以在awk中可以引用,例如

awk -v FS=‘/‘ ‘{print $1FS$3}‘ /etc/fstab

執行結果如下:
技術分享圖片
2.OFS:輸出字段分隔符,默認為空白字符,復制出一部分password內容用來演示,例如:
技術分享圖片

awk -v FS=: -v OFS=# ‘{print $1,$3}‘ /app/passwd

執行結果如下:
技術分享圖片
","表示引用輸出字段分割符,默認是空格,當定義了OFS後就是OFS了。
3.RS:輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效,例如:

awk -v FS=: -v RS=‘nologin‘ ‘{print $1,$3}‘ /app/passwd

執行結果如下:
技術分享圖片
可以看出整個文件被nologin分割為5段,稱為5個記錄,然後每個記錄以:作為域分割符,取出第1個域和第3個域。原有的換行符不再作為輸入記錄分割符,但是仍舊有效,輸出的內容中依然可以換行,例如:

awk -v OFS=‘:‘ -v FS=: -v RS=‘sbin‘ ‘{print $1,$3}‘ /app/passwd

執行結果如下:
技術分享圖片
/nologin加換行符和daemon被作為第二個記錄的第一個域輸出,域之間以:作為分割符,2是第三個域的內容。
4.ORS:輸出記錄分隔符,輸出時用指定符號代替輸入記錄分割符,例如:

awk -v ORS=‘#‘ -v RS=‘/sbin‘ ‘{print}‘ /app/passwd

執行結果如下:
技術分享圖片
可以看到原來的輸入記錄分割符‘/sbin’在輸出時被#替換,原來的換行符還有效,只是不作為記錄分割符
5.NF:字段數量,例如:

awk -v FS=: -v RS=‘/sbin‘ ‘{print NF}‘ /app/passwd

執行結果如下:
技術分享圖片
記錄按“/sbin”分割,而字段或者域用:分割。
6.NR:記錄號,例如:

awk -v RS=‘/sbin‘ ‘END{print NR}‘ /app/passwd

技術分享圖片
記錄被“/sbin”分割,然後用END生成統計結果,一共有11條記錄
7.FNR:各文件分別計數,記錄號,例如:

awk -v RS=‘/sbin‘ ‘{print FNR};END{print NR}‘ /app/passwd /app/passwd

技術分享圖片
記錄以"/sbin"分割,兩次對/app/passwd計數,最後用END生成統計結果,共有22條。
8.FILENAME:當前文件名,例如:

awk ‘{print FILENAME}‘ /app/passwd

技術分享圖片
9.ARGC:命令行參數的個數,例如:

awk ‘END{print ARGC}‘ /app/passwd /etc/passwd

執行結果如下:
技術分享圖片
一共有三個參數,第一個是awk,第二個是/app/passwd第三個是/etc/passwd
10.ARGV:數組,保存的是命令行所給定的各參數,例如:

 awk ‘END{print ARGV[0] }‘ /app/passwd /etc/passwd

打印命令行第一個參數,執行結果如下:
技術分享圖片

awk ‘END{print ARGV[ARGC-1] }‘ /app/passwd /etc/passwd

打印命令行的最後一個參數,執行結果如下:
技術分享圖片

4.自定義變量

自定義變量的方法如下:

awk -v test=123 ‘BEGIN{print test}‘

如上,定義了一個test變量,執行結果如下:
技術分享圖片
還可以在程序中定義變量,例如:

awk -v ‘test=134{print test,tooth;tooth=23}‘ /etc/fstab

執行結果如下:
技術分享圖片

5.格式化輸出

格式化輸出使用的是printf,當使用printf時,必須要為每一個輸出指定格式,例如:

awk -F: ‘{printf "UNAME:%-15s UID:%s\n",$1,$3}‘ /app/passwd

執行結果如下:
技術分享圖片

%s表示顯示字符串,-15表示左對齊15字符,\n代表換行,下面是常用的格式化控制符:
%c: 顯示字符的ASCII碼
%d: %i: 顯示十進制整數
%e: %E:顯示科學計數法數值
%f: 顯示為浮點數
%g: %G:以科學計數法或浮點形式顯示數值
%s: 顯示字符串
%u: 無符號整數
%%: 顯示%自身

還有一些修飾符:

    #[.#]:第一個數字控制顯示的寬度;第二個#表示小數點後精度,%3.1f
-: 左對齊(默認右對齊) %-15s
+:顯示數值的正負符號 %+d

6.操作符

1.算術操作符

+加-減*乘/除%取余^乘方
-x轉換為負數
+x轉換為數值

2.賦值操作符

=, +=, -=, *=, /=, %=, ^=
++, --

3.邏輯操作符

&&邏輯與
||邏輯或
!邏輯非

4.比較操作符

==等於
!=不等於
>大於
>=大於等於
<小於
<=小於等於

5.模式匹配符

~:左邊是否和右邊匹配包含
!~:是否不匹配

例如:

awk -F: ‘$0 ~ /root/    {print $1}‘  /etc/passwd

執行結果如下:
技術分享圖片
awk支持正則表達式,例如

awk -F: ‘$0 ~ "^root"    {print $1}‘  /etc/passwd

技術分享圖片
6.三目表達式
三目表達式的格式如下:

判斷?語句1:語句2

最開始先進行判斷,如果判斷結果為真,則執行語句1,如果判斷結果為假,則執行語句2,例如:

awk ‘BEGIN{1>3?a=1:a=3;print a}‘

執行結果如下:
技術分享圖片

7.awk action

1.awk循環
while循環
循環在條件為真開始循環,在條件為假時結束循環,例如:

awk  ‘BEGIN{i=1;while(i<10){ print i;i++}}‘

執行結果如下:
技術分享圖片
for循環
循環在滿足for的條件時開始循環,在不滿足for條件時結束循環,例如:

awk ‘BEGIN{for(i=1;i<10;i++)print i}‘

執行結果如下:
技術分享圖片
2.awk選擇
if選擇
如果滿足if後面條件,則執行之後的語句,否則不執行,進行其他的if判斷,最多有一個if被執行,例如:

awk -v i=9 ‘BEGIN{if(i<=5){print "小於等於5"}else if(i>5 && i<=10){print "大於5小於等於10"}else{print "大於10"}}‘

執行結果如下:
技術分享圖片
3.awk控制
continue控制
continue控制是結束當前這一次循環,直接進行下一次循環,例如:

awk ‘BEGIN{i=0;while(i<10){i++;if(i==5){continue} print i}}‘

執行結果如下:
技術分享圖片
當執行到i=5時,結束了循環,沒有輸出5,繼續下一次循環,即i=6的循環。
break控制
break控制是結束當前這一層循環,返還到上一級,例如:

awk ‘BEGIN{i=0;while(i<10){i++;if(i==5){break} print i}}‘

技術分享圖片
當執行到i=5時,結束了當前循環,退出當前的循環,沒有再進行打印5的操作以及之後的循環。
4.awk數組
我們常常用數組來看文件中某一列內容的重復次數,例如:

awk -F: ‘{line[$7]++}END{for(i in line){print i,line[i]}}‘ /etc/passwd

執行結果如下:
技術分享圖片
5.awk函數
awk函數一般是寫在一個文件中的,當需要時調用這個函數文件,例如:

function max(v1,v2) {
v1>v2?var=v1:var=v2
return var
}
BEGIN{a=3;b=2;print max(a,b)}

技術分享圖片
執行結果如下:
技術分享圖片
6.awk腳本
在awk中可以用system調用shell命令,例如:

awk ‘BEGIN{score=100; system("echo  your score is " score) }‘

執行結果如下:
技術分享圖片
我們可以用執行腳本的方法來執行awk例如:

#!/bin/awk –f
{if($3>=1000)print $1,$3}

將上面代碼寫入文件:
技術分享圖片
加上執行權限,並執行,結果如下:
技術分享圖片

文本三劍客之awk