Linux基礎系列 - 三劍客之 ack 命令使用總結
awk
是在linux環境下,分析文字的一個利器,與grep
、sed
被稱為linux三劍客。awk
功能強大,可以進行正則表示式的匹配,樣式裝入、流控制、數學運算子、程序控制語句甚至於內建的變數和函式。它具備了一個完整的語言所應具有的幾乎所有精美特性。awk
其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。實際上 AWK 的確擁有自己的語言: AWK 程式設計語言 , 三位建立者已將它正式定義為“樣式掃描和處理語言”。
使用方發
基本語法結構
語法: awk [options] 'script' var=value file(s) awk [options] -f scriptfile var=value file(s)
常用引數:
- -F fsfs指定輸入分隔符,fs可以是字串或正則表示式,如-F:
- -v var=value賦值一個使用者定義變數,將外部變數傳遞給awk
- -f scripfile從指令碼檔案中讀取awk命令
awk 的基本結構如下:
# awk 'BEGIN{ commands } pattern{ commands } END{ commands }' awk 'BEGIN{ print 'Start>>>' } ~/mysql/{ print $0 } END{ print "End" }' test.txt awk '{print $0}' test.txt
說明:
- BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變數初始化、列印輸出表格的表頭等語句通常可以寫在BEGIN語句塊中。
- END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如列印所有行的分析結果這類資訊彙總都是在END語句塊中完成,它也是一個可選語句塊。
- pattern語句塊中的通用命令是最重要的部分,它也是可選的。如果沒有提供pattern語句塊,則預設執行{ print },即列印每一個讀取到的行,awk讀取的每一行都會執行該語句塊。
- $0 為一個內建變數。
- /mysql/ 為正則表示式。
- ~ 表示模式開啟。
執行過程如下:
- 第一步:執行BEGIN{ commands }語句塊中的語句;
- 第二步:從檔案或標準輸入(stdin)讀取一行,然後執行pattern{ commands }語句塊,它逐行掃描檔案,從第一行到最後一行重複這個過程,直到檔案全部被讀取完畢。
- 第三步:當讀至輸入流末尾時,執行END{ commands }語句塊。
內建變數
awk 有些內建的變數,我們可以直接呼叫來使用:
說明:[A][N][P][G]表示第一個支援變數的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk,nawk/POSIXawk/gawk均為awk的擴充套件版本。 $n 當前記錄的第n個欄位,比如n為1表示第一個欄位,n為2表示第二個欄位。 $0 這個變數包含執行過程中當前行的文字內容。 [N] ARGC 命令列引數的數目。 [G] ARGIND 命令列中當前檔案的位置(從0開始算)。 [N] ARGV 包含命令列引數的陣列。 [G] CONVFMT 數字轉換格式(預設值為%.6g)。 [P] ENVIRON 環境變數關聯陣列。 [N] ERRNO 最後一個系統錯誤的描述。 [G] FIELDWIDTHS 欄位寬度列表(用空格鍵分隔)。 [A] FILENAME 當前輸入檔案的名。 [P] FNR 同NR,但相對於當前檔案。 [A] FS Begin中定義欄位分隔符(預設是任何空格)。 [G] IGNORECASE 如果為真,則進行忽略大小寫的匹配。 [A] NF 表示欄位數,在執行過程中對應於當前的欄位數。 [A] NR 表示記錄數,在執行過程中對應於當前的行號。 [A] OFMT 數字的輸出格式(預設值是%.6g)。 [A] OFS 輸出欄位分隔符(預設值是一個空格)。 [A] ORS 輸出記錄分隔符(預設值是一個換行符)。 [A] RS 記錄分隔符(預設是一個換行符)。 [N] RSTART 由match函式所匹配的字串的第一個位置。 [N] RLENGTH 由match函式所匹配的字串的長度。 [N] SUBSEP 陣列下標分隔符(預設值是34)。
這些變數我們再處理文字是可直接使用。例如,我要獲取每行文字的最後一個欄位,我就可以這樣寫:
awk '{print $NF}'
引數
-F
預設awk會將每行文字字元按空格來分成若干欄位再來進一步處理,可以使用此引數來自定義awk的行分割符號。
例項,
awk -F "." test.txt
-v
可以將外部值(並非來自stdin)傳遞給awk。
VAR=10000 echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
# 其他賦值 var1="aaa" var2="bbb" echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2 # 從檔案中獲取變數 awk '{ print v1,v2 }' v1=$var1 v2=$var2 filename
-f
awk 命令可寫入檔案,通過此引數呼叫。
# cal.awk {print $0} # 通過檔案呼叫 awk -f cal.awk test.txt
運算
條件表示式
==!=>>=
awk -F”:” ‘$1==”mysql”{print $3}’ /etc/passwd
awk -F”:” ‘{if($1==”mysql”) print $3}’ /etc/passwd//與上面相同
awk -F”:” ‘$1!=”mysql”{print $3}’ /etc/passwd//不等於
awk -F”:” ‘$3>1000{print $3}’ /etc/passwd//大於
awk -F”:” ‘$3>=100{print $3}’ /etc/passwd//大於等於
awk -F”:” ‘$3<1{print $3}’ /etc/passwd//小於
awk -F”:” ‘$3<=1{print $3}’ /etc/passwd//小於等於
邏輯運算子
&&||
awk -F: ‘$1~/mail/ && $3>8 {print }’ /etc/passwd//邏輯與,$1匹配mail,並且$3>8
awk -F: ‘{if($1~/mail/ && $3>8) print }’ /etc/passwd
awk -F: ‘$1~/mail/ || $3>1000 {print }’ /etc/passwd//邏輯或
awk -F: ‘{if($1~/mail/ || $3>1000) print }’ /etc/passwd
數值運算
awk -F: ‘$3 > 100’ /etc/passwd
awk -F: ‘$3 > 100 || $3 < 5’ /etc/passwd
awk -F: ‘$3+$4 > 200’ /etc/passwd
awk -F: ‘/mysql|mail/{print $3+10}’ /etc/passwd//第三個欄位加10列印
awk -F: ‘/mysql/{print $3-$4}’ /etc/passwd//減法
awk -F: ‘/mysql/{print $3*$4}’ /etc/passwd//求乘積
awk ‘/MemFree/{print $2/1024}’ /proc/meminfo//除法
awk ‘/MemFree/{print int($2/1024)}’ /proc/meminfo//取整
控制語句
IF語句
必須用在{}中,且比較內容用()擴起來
awk -F: ‘{if($1~/mail/) print $1}’ /etc/passwd//簡寫
awk -F: ‘{if($1~/mail/) {print $1}}’/etc/passwd//全寫
awk -F: ‘{if($1~/mail/) {print $1} else {print $2}}’ /etc/passwd//if…else…
while語句
awk -F: ‘BEGIN{i=1} {while(i<NF) print NF,$i,i++}’ /etc/passwd
for語句
seq 9 | sed ‘H;g’ | awk -v RS=’’ ‘{for(i=1;i<=NF;i++)printf(“%dx%d=%d%s”, i, NR, i*NR, i==NR?”\n”:”\t”)}’
常用總結
IP相關統計
#統計IP訪問量(獨立ip訪問數量) awk '{print $1}' access.log | sort -n | uniq | wc -l # 檢視某一時間段的IP訪問量(4-5點) grep "07/Apr/2017:0[4-5]" access.log | awk '{print $1}' | sort | uniq -c| sort -nr | wc -l # 檢視訪問最頻繁的前100個IP awk '{print $1}' access.log | sort -n |uniq -c | sort -rn | head -n 100 # 檢視訪問100次以上的IP awk '{print $1}' access.log | sort -n |uniq -c |awk '{if($1 >100) print $0}'|sort -rn # 查詢某個IP的詳細訪問情況,按訪問頻率排序 grep '127.0.01' access.log |awk '{print $7}'|sort |uniq -c |sort -rn |head -n 100
頁面訪問統計
# 檢視訪問最頻的頁面(TOP100) awk '{print $7}' access.log | sort |uniq -c | sort -rn | head -n 100 # 檢視訪問最頻的頁面([排除php頁面】(TOP100) grep -v ".php"access.log | awk '{print $7}' | sort |uniq -c | sort -rn | head -n 100 # 檢視頁面訪問次數超過100次的頁面 cat access.log | cut -d ' ' -f 7 | sort |uniq -c | awk '{if ($1 > 100) print $0}' | less # 檢視最近1000條記錄,訪問量最高的頁面 tail -1000 access.log |awk '{print $7}'|sort|uniq -c|sort -nr|less
請求量統計
# 統計每秒的請求數,top100的時間點(精確到秒) awk '{print $4}' access.log |cut -c 14-21|sort|uniq -c|sort -nr|head -n 100 # 統計每分鐘的請求數,top100的時間點(精確到分鐘) awk '{print $4}' access.log |cut -c 14-18|sort|uniq -c|sort -nr|head -n 100 # 統計每小時的請求數,top100的時間點(精確到小時) awk '{print $4}' access.log |cut -c 14-15|sort|uniq -c|sort -nr|head -n 100
效能分析
在nginx log中最後一個欄位加入$request_time
# 列出傳輸時間超過 3 秒的頁面,顯示前20條 cat access.log|awk '($NF > 3){print $7}'|sort -n|uniq -c|sort -nr|head -20 # 列出php頁面請求時間超過3秒的頁面,並統計其出現的次數,顯示前100條 cat access.log|awk '($NF > 1 &&$7~/\.php/){print $7}'|sort -n|uniq -c|sort -nr|head -100
蜘蛛抓取統計
# 統計蜘蛛抓取次數 grep 'Baiduspider' access.log |wc -l # 統計蜘蛛抓取404的次數 grep 'Baiduspider' access.log |grep '404' | wc -l
TCP連線統計
# 檢視當前TCP連線數 netstat -tan | grep "ESTABLISHED" | grep ":80" | wc -l # 用tcpdump嗅探80埠的訪問看看誰最高 tcpdump -i eth0 -tnn dst port 80 -c 1000 | awk -F"." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr
參考
- ofollow,noindex">http://man.linuxde.net/awk#%E8%B5%8B%E5%80%BC%E8%BF%90%E7%AE%97%E7%AC%A6
- http://blog.chinaunix.net/uid-23302288-id-3785105.html