一、基礎用法
awk:報告生成工具;把檔案中讀取到的每一行的每個字段分别進行格式化,然後進行顯示。
1
2
3
4
5
6
7
8
9
10
11
<code>[Linux85]</code><code>#awk -h</code>
<code>Usage: awk [POSIX </code><code>or</code> <code>GNU style options] </code><code>-</code><code>f progfile [</code><code>-</code><code>-</code><code>] </code><code>file</code> <code>...</code>
<code>Usage: awk [POSIX </code><code>or</code> <code>GNU style options] [</code><code>-</code><code>-</code><code>] </code><code>'program'</code> <code>file</code> <code>...</code>
<code>POSIX options: GNU </code><code>long</code> <code>options:</code>
<code> </code><code>-</code><code>f progfile </code><code>-</code><code>-</code><code>file</code><code>=</code><code>progfile</code>
<code> </code><code>-</code><code>F fs </code><code>-</code><code>-</code><code>field</code><code>-</code><code>separator</code><code>=</code><code>fs </code><code>#字段分隔符</code>
<code> </code><code>-</code><code>v var</code><code>=</code><code>val </code><code>-</code><code>-</code><code>assign</code><code>=</code><code>var</code><code>=</code><code>val</code>
<code> </code><code>-</code><code>m[fr] val</code>
<code> </code>
<code>awk [options] </code><code>'script'</code> <code>FILE</code> <code>...</code>
<code>awk [options] </code><code>'/pattern/{action}'</code> <code>FILE</code> <code>...</code>
四種分隔符:
輸入/輸出
行分隔符:$
字段分隔符:空白
模式
位址定界
/pattern1/,/pattern2/
/pattern/
可以 ! 取反
expression
表達式;>, >=, <, <=, ==, !=, ~
BEGIN{}
在周遊操作開始之前執行一次
END{}
在周遊操作結束之後、指令退出之前執行一次
<code>[Linux85]</code><code>#awk '/^soul/{print $0}' /etc/passwd /etc/shadow /etc/group</code>
<code>soul:x:</code><code>501</code><code>:</code><code>501</code><code>::</code><code>/</code><code>home</code><code>/</code><code>soul:</code><code>/</code><code>bin</code><code>/</code><code>bash</code>
<code>soul:!!:</code><code>16166</code><code>:</code><code>0</code><code>:</code><code>99999</code><code>:</code><code>7</code><code>:::</code>
<code>soul:x:</code><code>501</code><code>:</code>
<code>[Linux85]</code><code>#</code>
<code>#ID号大于等于500的使用者</code>
<code>[Linux85]</code><code>#awk -F : '$3>=500{print $1}' /etc/passwd</code>
<code>nfsnobody</code>
<code>gentoo</code>
<code>soul</code>
<code>BEGIN執行前操作</code>
<code>[Linux85]</code><code>#awk -F : 'BEGIN{print "UserName\n***********"}$3>=500{print $1}' /etc/passwd</code>
<code>UserName</code>
<code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code>
awk的内置變量:
NF
字段數( The number of fields in the current input record.)
FS
field separator,讀取文本時,所使用字段分隔符
RS
Record separator,輸入文本資訊所使用的換行符;
OFS
輸出時使用字段分隔符,預設為空白(output field separator)
ORS
output record separator
<code>[Linux85]</code><code>#awk -F : '/^soul/{print $1,$7}' /etc/passwd</code>
<code>soul </code><code>/</code><code>bin</code><code>/</code><code>bash</code>
<code> </code>
<code>[Linux85]</code><code>#awk 'BEGIN{FS=":"}/^soul/{print $1,$7}' /etc/passwd</code>
<code>[Linux85]</code><code>#awk 'BEGIN{FS=":";OFS=":"}/^soul/{print $1,$7}' /etc/passwd</code>
<code>soul:</code><code>/</code><code>bin</code><code>/</code><code>bash</code>
12
13
14
15
<code>[Linux85]</code><code>#awk '!/^$|^#/{print $1}' /etc/sysctl.conf</code>
<code>net.ipv4.ip_forward</code>
<code>net.ipv4.conf.default.rp_filter</code>
<code>net.ipv4.conf.default.accept_source_route</code>
<code>kernel.sysrq</code>
<code>kernel.core_uses_pid</code>
<code>net.ipv4.tcp_syncookies</code>
<code>net.bridge.bridge</code><code>-</code><code>nf</code><code>-</code><code>call</code><code>-</code><code>ip6tables</code>
<code>net.bridge.bridge</code><code>-</code><code>nf</code><code>-</code><code>call</code><code>-</code><code>iptables</code>
<code>net.bridge.bridge</code><code>-</code><code>nf</code><code>-</code><code>call</code><code>-</code><code>arptables</code>
<code>kernel.msgmnb</code>
<code>kernel.msgmax</code>
<code>kernel.shmmax</code>
<code>kernel.shmall</code>
<code>[Linux85]</code><code>#ifconfig | awk '/inet addr/{print $2}' | awk -F : '!/127/{print $2}'</code>
<code>172.16</code><code>.</code><code>251.85</code>
二、awk的進階使用
1、print輸出:print item1, item2, ...
各項目之間使用逗号隔開,而輸出時則以空白字元分隔;
輸出的item可以為字元串或數值、目前記錄的字段(如$1)、變量或awk的表達式;數值會先轉換為字元串,而後再輸出;
print指令後面的item可以省略,此時其功能相當于print $0, 是以,如果想輸出空白行,則需要使用print "";
2、printf輸出:printf format, item1, item2, ...
其與print指令的最大不同是,printf需要指定format;
format用于指定後面的每個item的輸出格式;
printf語句不會自動列印換行符;\n
format格式的訓示符都以%開頭;後面跟一個字元;
%c
顯示字元的ASCII碼;
%d | %i
十進制整數;
%e | %E
科學計數法顯示數值;
%f
顯示浮點數;
%g | %G
以科學計數法的格式或浮點數的格式顯示數值;
%s
顯示字元串;
%u
無符号整數;
%%
顯示%自身;
<code>[Linux85]</code><code>#awk 'BEGIN{num1=20;num2=30; printf "%d %d\n",num1,num2}'</code>
<code>20</code> <code>30</code>
<code>#不顯示item;隻顯示的是格式;格式對應的後面的變量;是以需要一一對應</code>
修飾符
N
顯示寬度
-
左對齊
+
顯示數值符号;正負數
<code>[Linux85]</code><code>#awk -F: '{printf "%-14s %s\n",$1,$NF}' /etc/passwd</code>
<code>root </code><code>/</code><code>bin</code><code>/</code><code>bash</code>
<code>bin</code> <code>/</code><code>sbin</code><code>/</code><code>nologin</code>
<code>daemon </code><code>/</code><code>sbin</code><code>/</code><code>nologin</code>
<code>adm </code><code>/</code><code>sbin</code><code>/</code><code>nologin</code>
<code>lp </code><code>/</code><code>sbin</code><code>/</code><code>nologin</code>
<code>sync </code><code>/</code><code>bin</code><code>/</code><code>sync</code>
3、awk内置變量之資料變量
NR
The number of input records,awk指令所處理的記錄數;如果有多個檔案,這個數目會把處理的多個檔案中行統一計數;
Number of Field,目前記錄的field個數;
FNR
與NR不同的是,FNR用于記錄正處理的行是目前這一檔案中被總共處理的行數;
ARGV
數組,儲存指令行本身這個字元串,如awk '{print $0}' a.txt b.txt這個指令中,ARGV[0]儲存awk,ARGV[1]儲存a.txt;
ARGC
awk指令的參數的個數;
FILENAME
awk指令所處理的檔案的名稱;
ENVIROM
目前shell環境變量及其值的關聯數組;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<code>[Linux85]</code><code>#awk '{print NR,$0}' 1.txt</code>
<code>1</code> <code>one line</code>
<code>2</code> <code>two line</code>
<code>3</code> <code>three line</code>
<code>4</code> <code>four line</code>
<code>5</code> <code>five line</code>
<code>[Linux85]</code><code>#awk '{print NR,$0}' 2.txt</code>
<code>1</code> <code>six line</code>
<code>2</code> <code>seven line</code>
<code>3</code> <code>eight line</code>
<code>4</code> <code>nine line</code>
<code>5</code> <code>ten line</code>
<code>[Linux85]</code><code>#awk '{print NR,$0}' 1.txt 2.txt</code>
<code>6</code> <code>six line</code>
<code>7</code> <code>seven line</code>
<code>8</code> <code>eight line</code>
<code>9</code> <code>nine line</code>
<code>10</code> <code>ten line</code>
<code>#</code>
<code>[Linux85]</code><code>#awk '{print FNR,$0}' 1.txt 2.txt</code>
<code>[Linux85]</code><code>#awk -F: '/root/{print $1,"is a user in",ARGV[1]}' /etc/passwd</code>
<code>root </code><code>is</code> <code>a user </code><code>in</code> <code>/</code><code>etc</code><code>/</code><code>passwd</code>
<code>operator </code><code>is</code> <code>a user </code><code>in</code> <code>/</code><code>etc</code><code>/</code><code>passwd</code>
<code>[Linux85]#awk </code><code>'BEGIN{print ARGC}'</code> <code>/etc/passwd /etc/group /etc/shadow</code>
<code>4</code>
<code>[Linux85]#</code>
<code># </code><code>'BEGIN{print ARGC}'</code><code>本身也當成一個參數</code>
<code>[Linux85]</code><code>#awk '{print $0,"in", FILENAME}' 1.txt 2.txt</code>
<code>one line </code><code>in</code> <code>1</code><code>.txt</code>
<code>two line </code><code>in</code> <code>1</code><code>.txt</code>
<code>three line </code><code>in</code> <code>1</code><code>.txt</code>
<code>four line </code><code>in</code> <code>1</code><code>.txt</code>
<code>five line </code><code>in</code> <code>1</code><code>.txt</code>
<code>six line </code><code>in</code> <code>2</code><code>.txt</code>
<code>seven line </code><code>in</code> <code>2</code><code>.txt</code>
<code>eight line </code><code>in</code> <code>2</code><code>.txt</code>
<code>nine line </code><code>in</code> <code>2</code><code>.txt</code>
<code>ten line </code><code>in</code> <code>2</code><code>.txt</code>
4、輸出重定向
print items > output-file
print items >> output-file
print items | command
特殊檔案描述符:
/dev/stdin:标準輸入
/dev/sdtout: 标準輸出
/dev/stderr: 錯誤輸出
/dev/fd/N: 某特定檔案描述符,如/dev/stdin就相當于/dev/fd/0;
5、awk的操作符
算術操作符
指派操作符
比較操作符
-x:負值
=:應[=]
x < y True if x is less than y.
+x:轉換為數值
+=
x <= y True if x is less than or equal to y.
x^y:次方
-=
x > y True if x is greater than y.
x**y:次方
*=
x >= y True if x is greater than or equal to y.
x*y
/=
x == y True if x is equal to y.
x/y
%=
x != y True if x is not equal to y.
x+y
^=
x ~ y True if the string x matches the regexp denoted by y.
x-y
**=
x !~ y True if the string x does not match the regexp denoted by y.
x%y
++
subscript in array True if the array array has an element with the subscript subscript.
--
awk中;任何非0值或非空字元串都為真;反之為假。
條件表達式:
select?if-true-exp:if-false-exp
6、模式和常見的模式類型
模式:
awk 'program' input-file1 input-file2 ...
program:
pattern { action }
....
常見的模式:
Regexp
正規表達式,格式為/regular expression/
expresssion
表達式,其值非0或為非空字元時滿足條件,如:$1 ~ /foo/ 或 $1 == "soul",用運算符~(比對)和!~(不比對)。
Ranges
指定的比對範圍,格式為pat1,pat2
BEGIN/END
特殊模式,僅在awk指令執行前運作一次或結束前運作一次
Empty(空模式)
比對任意輸入行;
常見的Action
Expressions
Control statements
Compound statements
Input statements
Output statements
7、控制語句
if-else
文法:if (condition) {then-body} else {[ else-body ]}
<code>[Linux85]</code><code>#awk -F : 'BEGIN{OFS=":"}{if ($3==0) {print $1,"Administrator";} else {print $1,"Common User"}}' /etc/passwd</code>
<code>root:Administrator</code>
<code>bin</code><code>:Common User</code>
<code>daemon:Common User</code>
<code>adm:Common User</code>
<code>lp:Common User</code>
<code>sync:Common User</code>
<code>shutdown:Common User</code>
<code>[Linux85]</code><code>#awk -F: '{if ($1=="root") printf "%-15s: %s\n",$1,"Admin";else printf "%-15s: %s\n",$1,"Common User"}' /etc/passwd</code>
<code>root : Admin</code>
<code>bin</code> <code>: Common User</code>
<code>daemon : Common User</code>
<code>adm : Common User</code>
<code>lp : Common User</code>
<code>sync : Common User</code>
<code>shutdown : Common User</code>
<code>halt : Common User</code>
<code>mail : Common User</code>
<code>uucp : Common User</code>
<code>operator : Common User</code>
<code>games : Common User</code>
<code>gopher : Common User</code>
<code>ftp : Common User</code>
<code>nobody : Common User</code>
<code>dbus : Common User</code>
<code>usbmuxd : Common User</code>
<code>[Linux85]</code><code>#awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd</code>
<code>3</code>
<code>[Linux85]</code><code>#統計uid>=500的使用者個數</code>
while
文法:while (condition){statement1; statment2; ...}
<code>[Linux85]</code><code>#awk -F : '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd</code>
<code>root</code>
<code>x</code>
<code>0</code>
<code>bin</code>
<code>1</code>
<code>#列印出/etc/passwd前三個字段</code>
<code>[Linux85]</code><code>#awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd</code>
<code>/</code><code>root</code>
<code>/</code><code>bin</code><code>/</code><code>bash</code>
<code>/</code><code>bin</code>
<code>/</code><code>sbin</code><code>/</code><code>nologin</code>
do-while 至少執行一次循環體,不管條件滿足與否
文法:do {statement1, statement2, ...} while (condition)
<code>[Linux85]</code><code>#awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd</code>
<code>daemon</code>
<code>2</code>
<code>[Linux85]</code><code>#awk -F: '{i=4;do {print $i;i--}while(i>4)}' /etc/passwd</code>
<code>7</code>
<code>12</code>
for
文法:for (variable assignment; condition; iteration process) {statement1, statement2, ...}
<code>[Linux85]</code><code>#awk -F: '{for(i=1;i<=3;i++) if (i<3){printf "%s:",$i} print $i}' /etc/passwd</code>
<code>root:x:</code><code>0</code>
<code>bin</code><code>:x:</code><code>1</code>
<code>daemon:x:</code><code>2</code>
<code>adm:x:</code><code>4</code>
<code>lp:x:</code><code>7</code>
<code>sync:x:</code><code>0</code>
<code>shutdown:x:</code><code>0</code>
for循環周遊數組元素
文法: for (i in array) {statement1, statement2, ...}
<code>[Linux85]</code><code>#awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd</code>
<code> </code><code>/</code><code>sbin</code><code>/</code><code>shutdown:</code><code>1</code>
<code> </code><code>/</code><code>bin</code><code>/</code><code>csh:</code><code>1</code>
<code> </code><code>/</code><code>bin</code><code>/</code><code>bash:</code><code>2</code>
<code> </code><code>/</code><code>sbin</code><code>/</code><code>nologin:</code><code>29</code>
<code> </code><code>/</code><code>sbin</code><code>/</code><code>halt:</code><code>1</code>
<code> </code><code>/</code><code>bin</code><code>/</code><code>sync:</code><code>1</code>
<code>#統計最後一個字段出現的次數</code>
case
文法:switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...}
break 和 continue
next
提前結束對本行文本的處理,并接着處理下一行;
<code>[Linux85]</code><code>#awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd</code>
<code>bin</code> <code>1</code>
<code>adm </code><code>3</code>
<code>sync </code><code>5</code>
<code>halt </code><code>7</code>
<code>operator </code><code>11</code>
<code>gopher </code><code>13</code>
<code>nobody </code><code>99</code>
<code>dbus </code><code>81</code>
<code>usbmuxd </code><code>113</code>
<code>vcsa </code><code>69</code>
<code>rtkit </code><code>499</code>
<code>abrt </code><code>173</code>
<code>postfix </code><code>89</code>
<code>rpcuser </code><code>29</code>
<code>pulse </code><code>497</code>
<code>soul </code><code>501</code>
8、數組
array[index-expression]
index-expression可以使用任意字元串;需要注意的是,如果某資料組元素事先不存在,那麼在引用其時,awk會自動建立此元素并初始化為空串;是以,要判斷某資料組中是否存在某元素,需要使用index in array的方式。
要周遊數組中的每一個元素,需要使用如下的特殊結構:
for (var in array) { statement1, ... }
其中,var用于引用數組下标,而不是元素值;
删除數組中的變量:delete array[index]
<code>[Linux85]</code><code>#netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'</code>
<code>ESTABLISHED </code><code>2</code>
<code>LISTEN </code><code>10</code>
9、awk的内置函數
split(string, array [, fieldsep [, seps ] ])
将string表示的字元串以fieldsep為分隔符進行分隔,并将分隔後的結果儲存至array為名的數組中;數組下标為從1開始的序列;
<code>[Linux85]</code><code>#df -lh | awk '!/^File/{split($5,percent,"%");if(percent[1]>=10){print $1}}'</code>
<code>/</code><code>dev</code><code>/</code><code>sda1</code>
<code>/</code><code>dev</code><code>/</code><code>mapper</code><code>/</code><code>vg0</code><code>-</code><code>usr</code>
<code>#磁盤使用率大于等于%10的顯示出來</code>
length([string]):傳回string字元串中字元的個數;
<code>[Linux85]</code><code>#awk -F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}' /etc/passwd</code>
<code>/</code><code>sbin</code>
substr(string, start [, length ])
取string字元串中的子串,從start開始,取length個;start從1開始計數;
system(command):執行系統command并将結果傳回至awk指令
systime():取系統目前時間
tolower(s):将s中的所有字母轉為小寫
toupper(s):将s中的所有字母轉為大寫
10、使用者自定義函數
自定義函數使用function關鍵字。格式如下:
function F_NAME([variable])
{
statements
}
example:
<code>#統計目前系統上每個用戶端IP的連接配接中狀處于ESTABLISHED的連接配接态的個數;</code>
<code>[Linux85]</code><code>#netstat -tn | awk '/ESTABLISHED\>/{split($5,ip,":");num[ip[1]]++}END{for (i in num) printf "%s %d\n", i, num[i]}'</code>
<code>172.16</code><code>.</code><code>254.28</code> <code>2</code>
<code>#統計ps aux指令執行時,目前系統上各狀态的程序的個數;</code>
<code>[Linux85]</code><code>#ps aux | awk '!/^USER/{state[$8]++}END{for (i in state) printf "%s %d\n",i,state[i]}'</code>
<code>S< </code><code>2</code>
<code>S<sl </code><code>1</code>
<code>Ss </code><code>18</code>
<code>SN </code><code>1</code>
<code>S </code><code>69</code>
<code>Ss</code><code>+</code> <code>6</code>
<code>Ssl </code><code>2</code>
<code>R</code><code>+</code> <code>1</code>
<code>S</code><code>+</code> <code>2</code>
<code>Sl </code><code>2</code>
<code>S<s </code><code>1</code>
<code>#統計ps aux指令執行時,目前系統上各使用者的程序的個數;</code>
<code>[Linux85]</code><code>#ps aux | awk '!/^USER/{state[$1]++}END{for (i in state) printf "%s %d\n",i,state[i]}'</code>
<code>rpc </code><code>1</code>
<code>dbus </code><code>1</code>
<code>68</code> <code>2</code>
<code>postfix </code><code>2</code>
<code>rpcuser </code><code>1</code>
<code>root </code><code>96</code>
<code>gentoo </code><code>2</code>
<code>#顯示ps aux指令執行時,目前系統上其VSZ(虛拟記憶體集)大于10000的程序及其PID;</code>
<code>[Linux85]</code><code>#ps aux | awk '!/USER/{if($5>10000) print $2,$11}'</code>
<code>1</code> <code>/</code><code>sbin</code><code>/</code><code>init</code>
<code>397</code> <code>/</code><code>sbin</code><code>/</code><code>udevd</code>
<code>1184</code> <code>auditd</code>
<code>1209</code> <code>/</code><code>sbin</code><code>/</code><code>rsyslogd</code>
<code>1251</code> <code>rpcbind</code>
<code>1282</code> <code>dbus</code><code>-</code><code>daemon</code>
<code>1292</code> <code>NetworkManager</code>
<code>1297</code> <code>/</code><code>usr</code><code>/</code><code>sbin</code><code>/</code><code>modem</code><code>-</code><code>manager</code>
<code>1311</code> <code>rpc.statd</code>
<code>1344</code> <code>cupsd</code>
<code>1354</code> <code>/</code><code>usr</code><code>/</code><code>sbin</code><code>/</code><code>wpa_supplicant</code>
<code>1392</code> <code>hald</code>
<code></code>
本文轉自Mr_陳 51CTO部落格,原文連結:http://blog.51cto.com/chenpipi/1391178,如需轉載請自行聯系原作者