1. 程式人生 > 其它 >Shell文字處理三劍客之——awk用法

Shell文字處理三劍客之——awk用法

1. 什麼是awk

AWK 是一種處理文字檔案的語言,是一個強大的文字分析工具。
之所以叫 AWK 是因為其取了三位創始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字元。
相較於sed常常作用於一整個行的處理,awk則比較傾向於一行當中分成數個欄位來處理,因為awk相當適合小型的文字資料。

2. 基本格式

awk [選項引數] 'script' var=value file(s)

awk [選項引數] -f scriptfile var=value file(s)

awk後面接兩個單引號並加上大括號{ }來設定想要對資料進行的處理操作,awk可以處理後續接的檔案,也可以讀取來自前個命令的標準輸,但如果awk主要是處理每一行的欄位內的資料時,預設的欄位分隔符為“空格鍵”或“Tab鍵”

3. 工作原理

逐行讀取文字,預設以空格或tab鍵為分隔符進行分隔,將分隔所得的各個欄位儲存到內建變數中, 並按模式或者條件執行編輯命令。
sed命令常用於一整行的處理,而awk比較傾向於將一行分成多個"欄位"然後再進行處理。awk資訊的讀入也是逐行讀取的,執行結果可以通過print的功能將欄位資料列印顯示。在使用awk命令的過程中,可以使用邏輯操作符"&&“表示"與”、"“表示"或”、"!“表示"非”;還可以進行簡單的數學運算,如+、-、*、/、%、^分別表示加、減、乘、除、取餘和乘方。

4. 常見的內建變數(可直接用)

FS∶ 列分割符。指定每行文字的欄位分隔符,預設為空格或製表位。與"-F"作用相同
NF∶ 當前處理的行的欄位個數。
NR∶ 當前處理的行的行號(序數)。
$0∶當前處理的行的整行內容。
$n∶ 當前處理行的第n個欄位(第n列)。
FILENAME∶ 被處理的檔名。
RS∶ 行分隔符。awk從檔案上讀取資料時,將根據RS的定義把資料切割成許多條記錄,而awk一次僅讀入一條記錄,以進行處理。預設值是’\n’

5. 按行輸出文字

例項1:輸出全部內容


例項2:輸出第1到第3行的內容

例項3:輸出第1行和第3行的內容,輸出奇數和偶數行

例項4:輸出包含指定字元的行

例項5:輸出包含指定字元的行並統計有多行
分析:

    1. BEGIN模式表示,在處理指定的文字之前,需要先執行BEGIN模式中指定的動作;
    2. awk再處理指定的文字,之後再執行END模式中指定的動作;
    3. END{ } 語句塊中,往往會放入列印結果等語句。

6. 按欄位輸出文字

例項1:輸出指定分隔符的指定欄位

例項2:輸出指定欄位在指定範圍內的行,並選擇輸出的欄位

例項2:awk結合三元運算子的使用。

例項3:輸出行和內容

例項4:輸出指定欄位中包含指定字元的行,然後輸出指定欄位

7. 通過管道、雙引號呼叫shell命令

例項1:輸出文字內容,結合awk以指定字元為分隔符,然後統計出行數

例項2:awk結合管道命令使用

例項3:檢視當前記憶體使用百分比

例項4:檢視當前系統的CPU的空閒率

例項5:顯示上次系統重啟的時間

8. 小案例 :awk集合getline、陣列的用法

案例1:統計線上使用者的數量
分析:

當getline左右無重定向符“<”或“1”時,awk首先讀取到了第一行,就是1,然後getline, 就得到了1下面的第二行,就是2,因為getline之後,awk會改變對應的NF, NR,FNR和$0等 內部變數,所以此時的$0的值就不再是1,而是2了,然後將它打印出來。
當getline左右有重定向符“<”或“I”時,getline則作用 於定向輸入檔案,由於該檔案是剛開啟,並沒有被awk讀入一行,只是getline讀入那麼getline返回的是該檔案的第一行, 而不是隔行。

案例2:分別顯示0到10的奇數和偶數行

案例3:指定分隔符來分隔字串

  • $1=$1是用來啟用$0的重新賦值,也就是說
  • 欄位$1…和欄位數NF的改變會促使awk重新計算$0的值,通常是在改變OFS後而需要輸出$0時這樣做

案例4:使用awk建立陣列,並迴圈

案例5:使用awk來統計httpd訪問日誌中每個客戶端IP出現的次數,超過三次進行提示。
awk '/Failed password/ {ip[$11]++}; END {for(i in ip){print i,ip[i]}}' /var/log/secure
1.先測試好提取ip和次數的正確命令,方便我們直接在腳本里面使用。

2.根據第一步的命令再次使用awk進行ip和次數的提取,然後做個if判斷即可。

ip_c=`awk '/Failed password/ {ip[$11]++}; END {for(i in ip){print i","ip[i]}}' /var/log/secure`
for j in $ip_c
{
ip=`echo $j | awk -F "," '{print $1}'`
num=`echo $j | awk -F "," '{print $2}'`
if [ $num -ge 3 ]
then
echo "注意!!$ip 訪問本機失敗次數為$num!請進行確認....."
fi
}