天天看點

Day06 awk一、awk基本用法二、awk進階應用

awk是一個程式設計語言/資料處理引擎。基于模式比對檢查輸入文本,逐行處理并輸出。

記錄:awk把每一個以換行符結束的行稱為一個記錄。

記錄分隔符:預設的輸入和輸出的分隔符都是回車,儲存在内建變量ORS和RS中。

記錄中每個單詞稱做“域”,預設情況下以空格或tab分隔。awk可跟蹤域的個數,并在内建變量NF中儲存該值。如$ awk '{print $1,$3}' test将列印test檔案中第一和第三個以空格分開的列(域)。

awk的基本模式是 pattern { action statements },action部分是可以省略的,預設情況下是輸出,即{print $0},至于pattern可以了解成是表達式,通過pattern表達式的值的真假,來确定是否要進行action。比如1,最簡單的awk用來實作cat的功能就是 awk '1',這邊1就是pattern,當然,1也可以是2,3,4,5等其他數字,但如果用字母的話,就不行,因為字母會解釋成變量,變量初始值未定義,初始值為假,或者可以加個!反義

awk [選項] '[條件]{編輯指令}' 檔案

前置指令 | awk [選項] '[條件]{編輯指令1};{編輯指令2}'

選項:F,v

條件:/正則/,數值/字元串比較,邏輯比較,運算符,BEGIN,END

編輯指令:print [變量],[常量]

變量:$n,$0,NF,NR 常量:必須以""括起來

指定分隔符,可省略(預設空格和tab位)

内建變量FS儲存輸入域分隔符的值,預設是空格或tab。可以同時使用多個域分隔符,這時應該把分隔符寫成放到方括号中,如$awk -F'[:\t]' '{print $1,$3}' test,表示以空格、冒号和tab作為分隔符。

輸出域的分隔符預設是一個空格,儲存在OFS中。如$ awk -F: '{print $1,$5}' test,$1和$5間的逗号就是OFS的值。

調用外部shell變量

a=1000

awk -v var=$a 'BEGIN {print var}'

變量 用途

FS 儲存或設定字段分隔符,例如FS=":"

$n 指定分割的第n個字段,如$1、$3分别表示第1、第3列

$0 目前讀入的整行文本内容

NF 記錄目前處理行的字段個數(列數)

NR 記錄目前已讀入行的數量(行數)

FNR 儲存目前處理行在原文本内的序号(行号)

FILENAME 儲存 awk 目前處理的(檔案名)

BEGIN子產品後緊跟着動作塊,這個動作塊在awk處理任何輸入檔案之前執行。是以它可以在沒有任何輸入的情況下進行測試。它通常用來改變内建變量的值,如OFS,RS和FS等,以及列印标題。如:$ awk 'BEGIN{FS=":"; OFS="\t"; ORS="\n\n"}{print $1,$2,$3}' test。上式表示,在處理輸入檔案以前,域分隔符(FS)被設為冒号,輸出檔案分隔符(OFS)被設定為制表符,輸出記錄分隔符(ORS)被設定為兩個換行符。$ awk 'BEGIN{print "TITLE TEST"}隻列印标題。

END不比對任何的輸入檔案,但是執行動作塊中的所有動作,它在整個輸入檔案處理完成後被執行。如$awk 'END{print "The number of records is" NR}' test,上式将列印所有被處理的記錄數。

在讀取檔案中執行n次。預設就是這個條件

這三種條件可以單獨使用,也可以組合使用

用來在記錄或者域内比對正規表達式

~表示列比對

!~表示對列比對取反

awk -F: '$0 ~/^root/' /etc/passwd 

root:x:0:0:root:/root:/bin/bash 

#在一整行中以root開頭

awk -F: '$0 ~/root/' /etc/passwd 

root:x:0:0:root:/root:/bin/bash

operator:x:11:0:operator:/root:/sbin/nologin

#在一整行中有root即可

==等于 !=不等于

>= < <= && || awk '$3>=9&&$3<=10' log#找出9:00-10:00的日志資訊 / % 普通加減乘除 ++ -- 自加自減,放在變量前後的意義有重要差別 ++var 先給var指派,再對var進行累加 var++ 先使用var變量的值,再對var進行累加 !a[$0]++  這個要從awk的執行模式開始說,最後結合++運算符,和hash特色 patten分析: 1.使用了一個hash數組a 2.這個數組a,又是使用$0這個變量作為下标,即檔案的每行值 3.當a[$0]未聲明(udef)時,a[$0]為假。但是在未聲明的情況下,進行一次a[$0]++後,a[$0]即為真 4.! 取反的優先級高于++ awk的基本模式是 ,pattern { action statements },action部分是可以省略的,預設情況下是輸出,即{print $0},至于pattern可以了解成是表達式,通過pattern表達式的值的真假,來确定是否要進行action 結論:當相同的行第一次讀入時,pattern為真,行輸出,再次讀入後,patten為假,行乎略。是以!a[$0]++可以去除一行中重複的記錄,以記錄作為數組(可以将a了解為數組)索引 a[$1]++ 和上面的表達式同理,可以根據記錄中某個域删除這個域相同的記錄,也可以根據這個域相同,執行另外一些相應的操作 += -= *= /= awk 'BEGIN{x=3;y=4;print x+y}' awk 'BEGIN{x=2;print x+y}'#就算y變量沒定義,也可以直接用,預設值為0 必須放在{}裡面才行 if單分支指令 if雙分支指令 if多分支指令 統計普通使用者有幾個?系統使用者有幾個? awk -F: '{if($3 < 1000){x++}else{y++}}END{print "normal users:"x,"super users:"y}' /etc/passwd if($3 < 1000){x++}else{y++} END{print x,y} while(條件){指令} for(條件){指令} awk 'BEGIN{a[xx]=11;a[yy]=22;print a[xx],a[yy]}' awk支援數組直接調用數組元素,而不是用0,1,2數字來調用 示例: 統計httpd_access_log的通路人數 準備工作: 使用ab軟體模拟100個人通路,每個人100000次點選,生成access_log 指令: awk '{ip[$1]++}END{for (i in ip){print i,ip[i]}}' /var/log/httpd/access_log |awk '$2>500{print $1}' 指令分解分析: ip[$1]是一個數組變量,下标為$1。$1也是變量,是讀取的檔案的第一列 ip[$1]++  第一次讀到ip[4.2]++,由于ip[4.2]不存在,首先指派為0,再自加1,是以得到的值ip[4.2]=1 第二次讀到ip[4.2],由于ip[4.2]已存在,使用原有值=1,再自加1,是以得到的值ip[4.2]=2 以此類推 for (i in ip){print i,ip[i]}是一個for循環,小括号裡面是判斷條件。i的值是ip這個數組的所有元素,即i in 4.2 4.5。 列印出來的結果 $1 $2 4.2 2 4.5 1 管道後的awk是用來判斷異常情況并輸出,$2>500的項就列印$1出來 ifconfig eth0|awk '/RX p/{print $5}' ifconfig eth0 |awk -F '[ :]+' 'NR==2 {print $4}' seq 100|awk '$1%7==0||$1~/7/' awk -F [:/] '{i=1}{while(i<=NF){if($i~/root/){j++};i++} }END{print j}' /etc/passwd awk是逐行讀入文本 讀入第一行的時候: 初始i=1,$1==root,條件比對j++=1 i++=1; $3=root,條件比對j++=2 i++=2 讀入第二行的時候 when i=2 so no $ equal root then j=2 after i=3 when i=3 so $1 equal root then j=3 after i=4 本文轉自 goldwinner 51CTO部落格,原文連結:http://blog.51cto.com/355665/2071221,如需轉載請自行聯系原作者