天天看點

Linux叢集和自動化維2.5 awk的基礎用法及實用示例

<b>2.5 awk的基礎用法及實用示例</b>

1. awk工具簡介

awk是一個強大的文本分析工具,相對于grep的查找、sed的編輯,awk在對資料進行分析并生成報告時,顯得尤為強大。簡單來說,awk就是把檔案逐行地讀入,然後以空格為預設分隔符将每行進行切片,切開的部分再進行各種分析處理。awk的名稱得自于它的創始人alfred

aho、peter weinberger 和brian kernighan 姓氏的首個字母。實際上awk的确擁有自己的語言:awk程式設計語言,三位建立者已将它正式定義為“樣式掃描和處理語言”。

awk允許我們建立簡短的程式,這些程式可讀取輸入檔案、為資料排序、處理資料、對輸入執行計算及生成報表,還有無數其他的功能。

2.使用方法

awk的指令格式如下:

awk 'pattern

{action}' filename

其中,pattern就是要表示的正規表達式,它表示awk在資料中查找的内容,而 action

是在找到比對内容時所執行的一系列指令。

awk語言的最基本功能是在檔案或字元串中基于指定的規則浏覽和抽取資訊,在抽取資訊後,才能進行其他文本操作。完整的awk腳本通常用來格式化文本檔案中的資訊。

通常,awk是以檔案的一行為處理機關的。awk每接收檔案的一行後,就會執行相應的指令來處理文本。

下面介紹一下awk程式設計模型。

awk程式由3部分組成,分别為:

初始化(處理輸入前做的準備,放在begin塊中)

資料處理(處理輸入資料)

收尾處理(處理輸入完成後要進行的處理,放到end塊中)

其中,在“資料處理”過程中,指令被寫成一系列模式/動作過程,模式用于測試輸入行的規則,以确定是否将規則應用于這些輸入行。

3. awk調用方式

awk主要有三種調用方式,下面分别來看看。

(1)指令行方式

awk [-f  field-separator] 'commands' filename

其中,commands是真正的awk指令,[-f域分隔符]是可選的,filename是待處理的檔案。

在awk檔案的各行中,由域分隔符分開的每一項稱為一個域。通常,在不指名-f域分隔符的情況下,預設的域分隔符是空格。

(2)使用-f選項調用awk 程式

awk允許将一段awk 程式寫入一個文本檔案中,然後在awk 指令行中用-f 選項調用并執行這段程式,指令如下:

awk -f

awk-script-file filename

其中,-f選項加載awk-script-file中的awk腳本,filename表示檔案名。

(3)利用指令解釋器調用awk 程式

利用linux系統支援的指令解釋器功能可以将一段awk

程式寫入文本檔案中,然後在它的第一行加上#!/bin/awk

–f。

4. awk詳細文法

與其他linux指令一樣,awk 擁有自己的文法:

awk [ -f re]

[parameter...] ['prog'] [-f progfile][in_file...]

其中,

-f re:允許awk更改其字段分隔符。

parameter:該參數幫助為不同的變量指派。

prog:awk的程式語句段。這個語句段必須用單引号'和'括起,以防被shell解釋。

前面已經提到過這個程式語句段的标準形式,如下所示:

其中pattern 參數可以是egrep 正規表達式中的任何一個,它可以使用文法/re/再加上一些樣式比對技巧構成。與sed

類似,也可以使用“,”分開兩種樣式以選擇某個範圍。

action參數總是被大括号包圍,它由一系列awk語句組成,各語句之間用“;”分隔。awk會解釋它們,并在pattern給定的樣式比對記錄上執行相關操作。

事實上,在使用該指令時可以省略pattern和action兩者中的某一個,但不能兩者同時省略。省略pattern表示沒有樣式比對,對所有行(記錄)均執行操作;省略action表示執行預設的操作—在标準輸出上顯示。

-f progfile:允許awk 調用并執行progfile指定的程式檔案。progfile是一個文本檔案,它必須符合awk 的文法。

in_file:awk的輸入檔案,awk 允許對多個輸入檔案進行處理。值得注意的是awk 不修改輸入檔案。

如果未指定輸入檔案,awk 将接受标準輸入,并将結果顯示在标準輸出上。

5. awk腳本編寫

(1)awk的内置變量

awk的内置變量主要有如下幾種。

fs:輸入資料的字段分隔符。

rs:輸入資料的記錄分隔符。

ofs:輸出資料的字段分隔符。

ors:輸出資料的記錄分隔符。另一類是系統自動改變的,比如:nf表示目前記錄的字段個數,nr表示目前記錄的編号等。

舉個例子,可用如下指令列印passwd中的第1個和第3個字段:

":" '{ print $1 "" $3 }' 

/tmp/passwd

(2)pattern/action模式

awk程式部分采用了pattern/action模式,即針對比對pattern的資料,使用action邏輯進行處理。來看下面這兩個例子。

判斷目前是不是空格,指令如下:

/^$/ {print

"this is a blank line!"}

判斷第5個字段是否含有“ma”,指令如下:

$5 ~ /ma/ {print

$1 "," $3}

(3)awk與shell混用

因為awk可以作為一個shell指令使用,是以awk能與shell腳本程式很好地融合在一起,這點為實作awk與shell程式的混合程式設計提供了可能。實作混合程式設計的關鍵是awk與shell腳本之間的對話,換言之,就是awk與shell 腳本之間的資訊交流:awk從shell腳本中擷取所需的資訊(通常是變量的值)、在awk 中執行shell指令行、shell腳本将指令執行的結果送給awk處理,以及shell腳本讀取awk的執行結果等,另外需要注意的是在shell腳本中讀取awk變量的方式,一般是通過" '$變量名' "的方式來讀取shell程式中的變量。

6. awk内置變量

awk有許多内置變量用于設定環境資訊,這些變量可以被改變,下面列舉了工作中最常用的一些awk變量,變量及其意義如下所示:

argc               指令行參數個數

argv               指令行參數排列

environ            支援隊列中系統環境變量的使用

filename           awk浏覽的檔案名

fnr                浏覽檔案的記錄數

fs                 設定輸入域分隔符,等價于指令行 -f選項

nf                 浏覽記錄的域的個數

nr                 已讀的記錄數

ofs                輸出域分隔符

ors                輸出記錄分隔符

rs                 控制記錄分隔符

此外,$0變量是指整條記錄。$1表示目前行的第一個域,$2表示目前行的第二個域……依次類推。

7. awk中的print和printf

awk中同時提供了print和printf兩種用于列印輸出的函數。

其中print函數的參數可以是變量、數值或字元串。字元串必須用雙引号引用,參數用逗号分隔。如果沒有逗号,參數就會串聯在一起而無法區分。這裡,逗号的作用與輸出檔案的分隔符的作用是一樣的,隻是後者是空格而已。

printf函數,其用法和c語言中printf函數基本相似,可以格式化字元串,輸出複雜結果時,printf的顯示結果更加人性化。

使用示例如下所示:

awk -f ':'

'{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\       n",filename,nr,nf,$0)}'

/tpm/passwd 

指令顯示結果如下所示:

filename:/tmp/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash

filename:/tmp/passwd,linenumber:2,columns:7,linecontent:bin:x:1:1:bin:/bin:/sbin/nologin

filename:/tmp/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin

filename:/tmp/passwd,linenumber:4,columns:7,linecontent:adm:x:3:4:adm:/var/adm:/sbin/nologin

filename:/tmp/passwd,linenumber:5,columns:7,linecontent:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

filename:/tmp/passwd,linenumber:6,columns:7,linecontent:sync:x:5:0:sync:/sbin:/bin/sync

filename:/tmp/passwd,linenumber:7,columns:7,linecontent:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

filename:/tmp/passwd,linenumber:8,columns:7,linecontent:halt:x:7:0:halt:/sbin:/sbin/halt

filename:/tmp/passwd,linenumber:9,columns:7,linecontent:mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

filename:/tmp/passwd,linenumber:10,columns:7,linecontent:uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

filename:/tmp/passwd,linenumber:11,columns:7,linecontent:operator:x:11:0:operator:/root:/sbin/nologin

filename:/tmp/passwd,linenumber:12,columns:7,linecontent:games:x:12:100:games:/usr/games:/sbin/nologin

filename:/tmp/passwd,linenumber:13,columns:7,linecontent:gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

filename:/tmp/passwd,linenumber:14,columns:7,linecontent:ftp:x:14:50:ftp

user:/var/ftp:/sbin/nologin

filename:/tmp/passwd,linenumber:15,columns:7,linecontent:nobody:x:99:99:nobody:/:/sbin/nologin

filename:/tmp/passwd,linenumber:16,columns:7,linecontent:vcsa:x:69:69:virtual

console memory owner:/dev:/sbin/nologin

filename:/tmp/passwd,linenumber:17,columns:7,linecontent:saslauth:x:499:76:"saslauthd

user":/var/empty/saslauth:/sbin/nologin

filename:/tmp/passwd,linenumber:18,columns:7,linecontent:postfix:x:89:89::/var/spool/postfix:/sbin/nologin

filename:/tmp/passwd,linenumber:19,columns:7,linecontent:sshd:x:74:74:privilege-separated

ssh:/var/empty/sshd:/sbin/nologin

filename:/tmp/passwd,linenumber:20,columns:7,linecontent:puppet:x:52:52:puppet:/var/lib/puppet:/sbin/nologin

filename:/tmp/passwd,linenumber:21,columns:7,linecontent:ntp:x:38:38::/etc/ntp:/sbin/nologin

filename:/tmp/passwd,linenumber:22,columns:7,linecontent:nagios:x:500:500::/home/nagios:/bin/bash

filename:/tmp/passwd,linenumber:23,columns:7,linecontent:apache:x:48:48:apache:/var/www:/sbin/nologin

filename:/tmp/passwd,linenumber:24,columns:7,linecontent:nginx:x:498:499:nginx

user:/var/cache/nginx:/sbin/nologin

參考文檔http://blog.pengduncun.com/?p=876。

8.工作示例

截取出init 中pid的示例指令如下:

ps -aux | grep

init | grep -v grep | awk '{print $2}'

截取網卡eth0的ipv4位址,示例指令如下:

ifconfig eth0

|grep "inet addr:" | awk -f: '{print $2}' |awk '{print $1}'

找出目前系統的自啟動服務,示例指令如下:

chkconfig --list

|grep 3:on | awk '{print $1}'

取出vmstat第4項的平均值,示例指令如下:

vmstat 1 4 |

egrep -v "io|free" | awk '{sum+=$4} end{print sum/4}'

以|為分隔符,彙總/yundisk/log/hadoop/下的hadoop第9項日志并列印,示例指令如下:

cat

/yundisk/log/hadoop/hadoop_clk_*.log | awk -f '|' 'begin{count=0} $2&gt;0             {count=count+$9} end {print count}'