gawk用法
?
?
一、awk概述
二、gawk工作機(jī)制
三、gawk命令介紹
?
?
一、awk概述
?
AWK的名字來(lái)自于其創(chuàng)始人Aho, Weinberger, Kernihan三人的名字首字母的組合。
?
awk是一個(gè)功能非常強(qiáng)大的文本處理工具,它能把文本當(dāng)做數(shù)據(jù)庫(kù),然后把數(shù)據(jù)庫(kù)中的每一行切分為多個(gè)字段,可以實(shí)現(xiàn)分別對(duì)多個(gè)字段或行進(jìn)行處理,并使之按照一定的格式輸出,所以awk是文本報(bào)告生成器,它能格式化文本。而要選擇性地處理字段或行,則可以使用模式(PATTERN)來(lái)匹配。
?
此外,awk已經(jīng)是一門(mén)獨(dú)立完整的編程語(yǔ)言,它支持一般編程語(yǔ)言所具備的特性,如支持變量、數(shù)組等數(shù)據(jù)結(jié)構(gòu)、支持條件判斷及循環(huán)等功能、具有內(nèi)置函數(shù)等。而正如前面所說(shuō),awk的主要是作為文本報(bào)告生成器來(lái)使用的。
?
gawk是GNU project的awk解釋器的開(kāi)放源代碼實(shí)現(xiàn),而nawk (new awk)則是20世紀(jì)80年代發(fā)展起來(lái)的新版本,不管是gawk還是nawk都是在其舊版本oawk (old awk)完善一些功能特性而來(lái)的。因?yàn)榇蠹腋鼉A向于使用awk及gawk,因此本文介紹的是gawk。
?
二、gawk工作機(jī)制
?
awk的工作流程首先是先讀取文本文件中的一行,并對(duì)這一行切分為多個(gè)字段,將每個(gè)字段都存放至awk的內(nèi)置變量($1,$2,$3,...)中,而當(dāng)前處理的一行則存放在awk內(nèi)置變量$0中。接著awk根據(jù)用戶(hù)指定的模式(PATTERN),分別對(duì)行或每一行中的字段進(jìn)行匹配,并根據(jù)用戶(hù)指定的動(dòng)作語(yǔ)句(Action)對(duì)匹配到的行或字段進(jìn)行加工處理;最后awk會(huì)將加工處理的結(jié)果默認(rèn)輸出至標(biāo)準(zhǔn)輸出,并開(kāi)始讀取文本文件的下一行進(jìn)行處理,以此類(lèi)推。
?
awk就是這樣來(lái)實(shí)現(xiàn)強(qiáng)大的文本處理功能的。不難想到,用戶(hù)可以通過(guò)模式匹配(PATTERN)選擇要處理的行或字段,而在動(dòng)作語(yǔ)句(Action)中指明要如何加工處理數(shù)據(jù)、數(shù)據(jù)以什么格式輸出等,如果有需要還可以利用Action中的條件判斷語(yǔ)句作進(jìn)一步選擇要處理和輸出的數(shù)據(jù),也可以通過(guò)循環(huán)語(yǔ)句實(shí)現(xiàn)對(duì)每一行字段間的遍歷或數(shù)組的各個(gè)元素的遍歷等。需要注意的是,awk具有內(nèi)生循環(huán),因此會(huì)自動(dòng)遍歷文本文件中的每一行。
?
三、gawk命令介紹
?
命令簡(jiǎn)述:
gawk - pattern scanning and processing language
gawk是文本處理工具,支持模式掃描,是一門(mén)編程語(yǔ)言。
????
語(yǔ)法格式:
gawk [options] 'program' FILE ...
?
常用選項(xiàng):
-F:用于指定輸入時(shí)用到的字段分隔符;
-v var=value:自定義變量;
?
program:
program:PATTERN{ACTION STATEMENTS}
①PATTERN:模式
②A(yíng)CTION STATEMENTS:動(dòng)作語(yǔ)句
?
PATTERN:
(1) empty:空模式,匹配每一行;
(2) /regular expression/:僅處理被此處的模式(正則表達(dá)式)所匹配到的行;
(3) relational expression:關(guān)系表達(dá)式;結(jié)果有“真”有“假”,結(jié)果為“真”時(shí)才執(zhí)行;
(4) lines ranges:指定行范圍;
(5) BEGIN/END模式:
①BEGIN{}:僅在開(kāi)始處理文件中的文本之前執(zhí)行一次;
②END{}:僅在文本處理完成之后、命令結(jié)束之前執(zhí)行一次;
?
?
我們從netstat命令中提取了如下信息作為使用示例:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># cat netstat.txt </span> Proto Recv-Q Send-Q Local-Address Foreign-Address State tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp 0 0 10.10.10.140:49808 10.10.10.140:80 TIME_WAIT tcp 0 52 10.10.10.140:22 10.10.10.1:52641 ESTABLISHED tcp 0 0 10.10.10.140:22 10.10.10.1:51926 ESTABLISHED tcp 0 0 10.10.10.140:22 10.10.10.1:52640 ESTABLISHED tcp 0 0 10.10.10.140:49806 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:49804 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:49810 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:49812 10.10.10.140:80 TIME_WAIT</code></span></span></span>?
要點(diǎn):
1.?$1,$2,...$n分別表示當(dāng)前處理的一行的第1個(gè)、第2個(gè)...第n個(gè)字段。
2. 使用print語(yǔ)句時(shí),在命令行可用逗號(hào)分隔各個(gè)字段,在輸出時(shí)默認(rèn)以空白字符作為分隔符。
?
(1) empty:空模式,匹配每一行
示例:
顯示第1列、第4列:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{print $1,$4}' netstat.txt </span> Proto Local-Address tcp 0.0.0.0:22 tcp 127.0.0.1:25 tcp 10.10.10.140:49808 tcp 10.10.10.140:22 tcp 10.10.10.140:22 tcp 10.10.10.140:22 tcp 10.10.10.140:49806 tcp 10.10.10.140:49804 tcp 10.10.10.140:49810 tcp 10.10.10.140:49812</code></span></span></span>因?yàn)槭强漳J?#xff0c;所以會(huì)匹配每一行。
?
?
(2) /regular expression/:僅處理被此處的模式(正則表達(dá)式)所匹配到的行;
示例:
顯示netstat.txt文件中以tcp開(kāi)頭的行:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '/^tcp\>/' netstat.txt </span> tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp 0 0 10.10.10.140:49808 10.10.10.140:80 TIME_WAIT tcp 0 52 10.10.10.140:22 10.10.10.1:52641 ESTABLISHED tcp 0 0 10.10.10.140:22 10.10.10.1:51926 ESTABLISHED tcp 0 0 10.10.10.140:22 10.10.10.1:52640 ESTABLISHED tcp 0 0 10.10.10.140:49806 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:49804 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:49810 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:49812 10.10.10.140:80 TIME_WAIT</code></span></span></span>?
顯示/etc/fstab文件中以'UUID'開(kāi)頭的行的第一個(gè)字段:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '/^UUID/{print $1}' /etc/fstab </span> UUID<span style="color:#9a6e3a">=</span>60eb0d1c-9834-4348-9a79-2f91983a8ede UUID<span style="color:#9a6e3a">=</span>3995456f-a3e9-4b69-a0de-0fd48068da39 UUID<span style="color:#9a6e3a">=</span>01d24b59-eee4-472e-9985-ef44fd5e059c <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray">#</span></code></span></span></span>?
顯示/etc/fstab文件中不以'UUID'開(kāi)頭的行的第一個(gè)字段:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '!/^UUID/{print $1}' /etc/fstab </span><span style="color:slategray">#</span> <span style="color:slategray">#</span> <span style="color:slategray">#</span> <span style="color:slategray">#</span> <span style="color:slategray">#</span> <span style="color:slategray">#</span> <span style="color:slategray">#</span> tmpfs devpts sysfs proc /dev/sr0 <span style="color:slategray">#/dev/md0</span> <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray">#</span></code></span></span></span>注意:對(duì)過(guò)濾模式取反,只需在模式前加上'!'即可。
?
?
(3) relational expression:關(guān)系表達(dá)式;結(jié)果有“真”有“假”,結(jié)果為“真”時(shí)才執(zhí)行
?
什么才是“真”?結(jié)果為非0值、非空字符串,即為真。
?
示例:
顯示/etc/passwd中最后一個(gè)字段為'/bin/bash'的用戶(hù)的用戶(hù)名、id及shell:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash">方式一: <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '$NF=="/bin/bash"{print $1,$3,$NF}' /etc/passwd</span> root 0 /bin/bash logstash 500 /bin/bash centos 501 /bin/bash方式二: <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '$NF~/\/bin\/bash$/{print $1,$3,$NF}' /etc/passwd</span> root 0 /bin/bash logstash 500 /bin/bash centos 501 /bin/bash</code></span></span></span>?
(4) lines ranges:指定行范圍
格式:
startline,endline:/pat1/,/pat2/
?
注意:不支持直接給出數(shù)字的格式,只能使用模式進(jìn)行匹配;
?
示例:
顯示/etc/passwd文件中第2行到第10行的第一個(gè)字段:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd</span> bin daemon adm lp <span style="color:#dd4a68">sync</span> <span style="color:#dd4a68">shutdown</span> halt mail uucp <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray">#</span></code></span></span></span>錯(cuò)誤示例:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '2,10{print $1}' /etc/passwd</span></code></span></span></span>注意這是錯(cuò)誤寫(xiě)法!因?yàn)椴荒苤苯咏o出行數(shù)!
?
(5) BEGIN/END模式:
①BEGIN{}:僅在開(kāi)始處理文件中的文本之前執(zhí)行一次;
②END{}:僅在文本處理完成之后、命令結(jié)束之前執(zhí)行一次;
?
示例:
指定分隔符為':':
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{FS=":"}{print $1,$3,$6}' /etc/passwd</span> root 0 /root bin 1 /bin daemon 2 /sbin adm 3 /var/adm lp 4 /var/spool/lpd <span style="color:#dd4a68">sync</span> 5 /sbin <span style="color:#dd4a68">shutdown</span> 6 /sbin halt 7 /sbin mail 8 /var/spool/mail</code></span></span></span>?
統(tǒng)計(jì)出當(dāng)前主機(jī)的tcp連接狀態(tài)為"LISTEN"的連接數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># netstat -tan</span> Active Internet connections <span style="color:#999999">(</span>servers and established<span style="color:#999999">)</span> Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp 0 52 10.10.10.140:22 10.10.10.1:51926 ESTABLISHED tcp6 0 0 :::80 :::* LISTEN tcp6 0 0 :::22 :::* LISTEN tcp6 0 0 ::1:25 :::* LISTEN <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># </span> <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># netstat -tan | awk '$NF=="LISTEN"{i++}END{print i}' </span> 5 <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray">#</span></code></span></span></span>?
說(shuō)到內(nèi)建變量,我們來(lái)看一看awk的內(nèi)建變量吧:
?
| FS | input field seperator,輸入時(shí)的字段分隔符,默認(rèn)為空白字符 |
| OFS | output field seperator,輸出時(shí)的字段分隔符,默認(rèn)為空白字符 |
| RS | input record seperator,輸入時(shí)的換行符,默認(rèn)為\n |
| ORS | output record seperator,輸出時(shí)的換行符,默認(rèn)為\n |
| NF | number of field,每一行的字段數(shù)量 |
| NR | number of record,行數(shù),顯示為當(dāng)前處理的行的行號(hào) |
| FNR | file number of record,行數(shù),各個(gè)文件分開(kāi)進(jìn)行計(jì)數(shù) |
| FILENAME | 當(dāng)前文件名 |
| ARGC | 命令行給定的參數(shù)個(gè)數(shù) |
| ARGV | 數(shù)組,保存的是命令行給定的各參數(shù) |
?
示例:
顯示/etc/passwd文件中每一行的第一個(gè)字段:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -v FS=":" '{print $1}' /etc/passwd</span> root bin daemon adm lp <span style="color:#dd4a68">sync</span> <span style="color:#dd4a68">shutdown</span> halt</code></span></span></span>顯示效果與直接用-F選項(xiàng)指出分隔符為':'相同。
?
顯示/etc/passwd文件中每一行的第1、3、7個(gè)字段,并且每個(gè)字段之間用冒號(hào)連接:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -v FS=":" -v OFS=":" '{print $1,$3,$7}' /etc/passwd</span> root:0:/bin/bash bin:1:/sbin/nologin daemon:2:/sbin/nologin adm:3:/sbin/nologin lp:4:/sbin/nologin sync:5:/bin/sync shutdown:6:/sbin/shutdown halt:7:/sbin/halt</code></span></span></span>?
顯示/etc/fstab文件中每一行的字段數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{print NF}' /etc/fstab </span> 0 1 2 10 1 9 12 1 6 6 6 6</code></span></span></span>?
顯示netstat.txt文件中每一行的最后一個(gè)字段:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{print $NF}' netstat.txt </span> State LISTEN LISTEN TIME_WAIT ESTABLISHED ESTABLISHED ESTABLISHED TIME_WAIT TIME_WAIT TIME_WAIT TIME_WAIT</code></span></span></span>這里需要注意NF和$NF的區(qū)別!我們說(shuō)過(guò),在awk中引用變量不需要帶上"$",即便是$1,$2,...也只是awk引用每一行中各個(gè)字段的專(zhuān)用符號(hào),這里NF表示當(dāng)前處理的行的字段數(shù)量,$NF則是將NF(即字段數(shù)量)的值作為"$#"中的數(shù)字"#",從而相當(dāng)于使用awk的專(zhuān)用符號(hào)!
?
?
顯示netstat.txt文件中每一行的行號(hào):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{print NR}' netstat.txt </span> 1 2 3 4 5 6 7 8 9 10 11</code></span></span></span>?
如果對(duì)一個(gè)文件的每一行進(jìn)行顯示的話(huà),則會(huì)顯示每一行的行號(hào);而在整個(gè)文件處理結(jié)束之后再進(jìn)行顯示時(shí),則顯示的是文件的行號(hào),如下:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'END{print NR}' netstat.txt </span> 11</code></span></span></span>?
顯示文件/etc/fstab和/etc/inittab的行數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{print NR}' /etc/fstab /etc/inittab </span> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29</code></span></span></span>可以發(fā)現(xiàn),這里將兩個(gè)文本文件當(dāng)做一個(gè)文件來(lái)處理了,而如果需要將兩個(gè)或多個(gè)文件分開(kāi)進(jìn)行計(jì)數(shù)時(shí),則可使用內(nèi)建變量NFR:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{print FNR}' /etc/fstab /etc/inittab </span> 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17</code></span></span></span>?
顯示命令行給定的參數(shù)個(gè)數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{print ARGC}' /etc/fstab /etc/inittab </span> 3</code></span></span></span>?
在命令行中給定的各個(gè)參數(shù)會(huì)存放在awk的內(nèi)建數(shù)組ARGV中,可使用ARGV[#]引用各個(gè)參數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/inittab </span> <span style="color:#dd4a68">awk</span> <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/inittab </span> /etc/fstab <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/inittab </span> /etc/inittab</code></span></span></span>注意:這里第一個(gè)參數(shù)是awk,而不是'program'!
?
?
除了內(nèi)建變量之外,awk還支持用戶(hù)自定義變量,而自定義變量有兩種方式:
(1) 通過(guò)選項(xiàng)-v var=value定義變量;
(2) 在program中直接定義;
?
命令演示:
也可通過(guò)選項(xiàng)直接定義:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -v test='hello awk' '{print test}' netstat.txt </span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span> hello <span style="color:#dd4a68">awk</span></code></span></span></span>文件有多少行,就顯示多少個(gè)'hello awk';這里引用變量不需要'$',再次強(qiáng)調(diào)!
?
如果不需要對(duì)各行處理,而僅顯示一次,則:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -v test='hello awk' 'BEGIN{print test}' netstat.txt </span> hello <span style="color:#dd4a68">awk</span></code></span></span></span>?
在program中定義:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{test="hello"; print test}'</span> hello</code></span></span></span>?
?
接下來(lái)介紹awk常用的Action:
?
(1) pirnt語(yǔ)句:
格式:
print item1, item2, ...
?
要點(diǎn):
①在命令中以逗號(hào)作為分隔符,輸出時(shí)默認(rèn)以空白字符作為分隔符;
②這里輸出的各item可以是字符串、數(shù)值、當(dāng)前記錄的字段、變量、數(shù)組以及awk的表達(dá)式等;
③如果輸出的數(shù)值,則數(shù)值會(huì)隱射為字符串后輸出,而在計(jì)算時(shí)仍為數(shù)值;
④如果省略item,輸出效果相當(dāng)于'print $0'.
?
示例:
顯示/etc/fstab文件中最后4行中每一行的第2、4個(gè)字段:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># tail -4 /etc/fstab | awk '{print $2,$4}'</span> / defaults /boot defaults /home defaults swap defaults</code></span></span></span>注意:如果在命令行中沒(méi)有使用逗號(hào)分隔,則會(huì)被awk認(rèn)為這是一個(gè)字段,并連接起來(lái),如下:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># tail -4 /etc/fstab | awk '{print $2 $4}'</span> /defaults /bootdefaults /homedefaults swapdefaults</code></span></span></span>?
在顯示的字段前插入字符串:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># tail -4 /etc/fstab | awk '{print "hello:",$2,$4}'</span> hello: / defaults hello: /boot defaults hello: /home defaults hello: swap defaults</code></span></span></span>?
需要注意的是,只有在引號(hào)之外才可以做變量替換,因此在awk中要做變量替換時(shí),不能用引號(hào)將之引起來(lái),這里舉一個(gè)例子:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># tail -4 /etc/fstab | awk '{print "hello:",$2}'</span> hello: / hello: /boot hello: /home hello: swap <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># tail -4 /etc/fstab | awk '{print "hello:,$2"}'</span> hello:,<span style="color:#ee9900">$2</span> hello:,<span style="color:#ee9900">$2</span> hello:,<span style="color:#ee9900">$2</span> hello:,<span style="color:#ee9900">$2</span></code></span></span></span>?
直接顯示每一行的內(nèi)容:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{print}' netstat.txt </span> Active Internet connections <span style="color:#999999">(</span>servers and established<span style="color:#999999">)</span> Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp 0 0 10.10.10.140:49808 10.10.10.140:80 TIME_WAIT tcp 0 52 10.10.10.140:22 10.10.10.1:52641 ESTABLISHED tcp 0 0 10.10.10.140:22 10.10.10.1:51926 ESTABLISHED tcp 0 0 10.10.10.140:22 10.10.10.1:52640 ESTABLISHED tcp 0 0 10.10.10.140:49806 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:49804 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:49810 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:49812 10.10.10.140:80 TIME_WAIT <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray">#</span></code></span></span></span>這里直接給出print相當(dāng)于'print $0'。
?
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{print ""}' netstat.txt </span><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray">#</span></code></span></span></span>awk會(huì)遍歷整個(gè)文件,文件有多少行,這里就顯示多少個(gè)空白行。
?
?
(2) printf語(yǔ)句:
語(yǔ)法:
printf "FORMAT" item1, item2, ...
?
功效:
格式化輸出:將各個(gè)item按位套進(jìn)"FORMAT"指定的格式中,實(shí)現(xiàn)按照一定格式輸出的功能。
?
要點(diǎn):
①"FORMAT"必須給出;
②不會(huì)自動(dòng)換行,需要顯式給出換行控制符"\n";
③"FORMAT"需要分別為后面的每個(gè)item指定一個(gè)格式化符號(hào)(格式符).
?
格式符:
%c:顯示為字符的ASCII碼;
%d, %i:顯示為十進(jìn)制整數(shù);
%e, %E:以科學(xué)計(jì)數(shù)法顯示;
%f:顯示為浮點(diǎn)數(shù);
%g, %G:以科學(xué)計(jì)數(shù)法或浮點(diǎn)形式顯示;
%s:顯示為字符串;
%u:顯示為無(wú)符號(hào)整數(shù);
%%:顯示%自身.
?
修飾符:
每個(gè)格式符還可以有修飾符,可通過(guò)在格式符前面加上一些修飾符以控制其格式的顯示機(jī)制,因此稱(chēng)為修飾符。
常用的修飾符有:
?#[.#]:第一個(gè)數(shù)字#表示顯示的寬度,后一個(gè)#表示小數(shù)點(diǎn)后的精度;
?-:以左對(duì)齊形式顯示;
+:顯示為數(shù)值的符號(hào).
?
示例:
格式化輸出/etc/passwd文件中的第1列:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '{printf "Username: %s\n",$1}' /etc/passwd</span> Username: root Username: bin Username: daemon Username: adm Username: lp Username: <span style="color:#dd4a68">sync</span> Username: <span style="color:#dd4a68">shutdown</span> Username: halt</code></span></span></span>?
格式化輸出/etc/passwd文件中的第1列和第3列:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '{printf "Username: %-18s UID: %d\n",$1,$3}' /etc/passwd</span> Username: root UID: 0 Username: bin UID: 1 Username: daemon UID: 2 Username: adm UID: 3 Username: lp UID: 4 Username: <span style="color:#dd4a68">sync</span> UID: 5 Username: <span style="color:#dd4a68">shutdown</span> UID: 6 Username: halt UID: 7</code></span></span></span>?
(3) 操作符
操作符可用于PATTERN或者Action中,操作符主要有以下幾種:
?
①算術(shù)操作符
雙目:
x+y, x-y, x*y, x/y, x%y, x^y
?
單目:
-x:取相反數(shù);
+x:將字符串轉(zhuǎn)換為數(shù)值;? ?
?
②字符串操作符
字符串切片:使用gawk內(nèi)建函數(shù);
沒(méi)有符號(hào)的操作符:表示連接字符串;
?
③比較操作符
>, >=
<, <=
==, !=
?
④賦值操作符
+=, -=, *=, /=, ^=, %=
++, --
?
⑤模式匹配符
~:左側(cè)的字符串是否被右側(cè)的PATTERN匹配;
!~:左側(cè)的字符串是否不被右側(cè)的PATTERN匹配;
?
⑥邏輯操作符
&&
||
!
?
⑦函數(shù)調(diào)用
無(wú)參數(shù)時(shí):
function_name()
?
有參數(shù)時(shí):
function_name(argu1, argu2, ...)
?
⑧條件表達(dá)式
selector?if-true-expression:if-false-expression
?
?
解釋:
"selector"是一個(gè)條件表達(dá)式,如果"selector"為真,則執(zhí)行"if-true-expression"語(yǔ)句;如果"selector"為假,則執(zhí)行"if-false-expression"語(yǔ)句。
?
示例:
顯示系統(tǒng)上所有用戶(hù)的用戶(hù)名及其說(shuō)明其用戶(hù)類(lèi)型:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or Sys</span> User<span style="color:#669900">";printf "</span>Username: %-18s Usertype: %s\n",<span style="color:#ee9900">$1</span>,usertype<span style="color:#999999">}</span>' /etc/passwd Username: root Usertype: Sysadmin or SysUser Username: bin Usertype: Sysadmin or SysUser Username: daemon Usertype: Sysadmin or SysUser Username: adm Usertype: Sysadmin or SysUser Username: lp Usertype: Sysadmin or SysUser Username: <span style="color:#dd4a68">sync</span> Usertype: Sysadmin or SysUser Username: <span style="color:#dd4a68">shutdown</span> Usertype: Sysadmin or SysUser Username: halt Usertype: Sysadmin or SysUser Username: mail Usertype: Sysadmin or SysUser Username: operator Usertype: Sysadmin or SysUser Username: games Usertype: Sysadmin or SysUser Username: <span style="color:#dd4a68">ftp</span> Usertype: Sysadmin or SysUser Username: nobody Usertype: Sysadmin or SysUser Username: systemd-bus-proxy Usertype: Sysadmin or SysUser Username: systemd-network Usertype: Sysadmin or SysUser Username: dbus Usertype: Sysadmin or SysUser Username: polkitd Usertype: Sysadmin or SysUser Username: tss Usertype: Sysadmin or SysUser Username: postfix Usertype: Sysadmin or SysUser Username: sshd Usertype: Sysadmin or SysUser Username: tab Usertype: Common User Username: geoclue Usertype: Sysadmin or SysUser Username: apache Usertype: Sysadmin or SysUser Username: centos Usertype: Common User</code></span></span></span>?
操作符同樣可使用在PATTERN中,例如,如果系統(tǒng)用戶(hù)的uid大于1000,則顯示其用戶(hù)名和uid(使用關(guān)系表達(dá)式):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '$3>=1000{printf "Username: %-10s UID: %s\n",$1,$3}' /etc/p</span> asswd Username: tab UID: 1000 Username: centos UID: 1001</code></span></span></span>?
(4) if-else條件判斷
語(yǔ)法格式:
if(condition) {statements}
if(condition) {statements} else {statements}
?
注意:
如果"{statements}"中只有一個(gè)語(yǔ)句時(shí),則其花括號(hào)'{}'可省略;如果"{statements}"中有多個(gè)語(yǔ)句時(shí),則其花括號(hào)'{}'不可省略!以下其他語(yǔ)句類(lèi)同。
?
使用場(chǎng)景:
需要對(duì)awk取得的整行或某個(gè)字段做條件判斷時(shí)使用。
?
用法示例:
像剛才的例子,如果系統(tǒng)用戶(hù)的uid大于1000,則顯示其用戶(hù)名和uid,這里使用if-else語(yǔ)句來(lái)實(shí)現(xiàn):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '{if($3>=1000) {printf "Username: %-18s Usertype: Common Us</span> er\n<span style="color:#669900">",<span style="color:#ee9900">$1</span>} else {printf "</span>Username: %-18s Usertype: Sysadmin or SysUser\n",<span style="color:#ee9900">$1</span><span style="color:#999999">}</span><span style="color:#999999">}</span>' /etc/pas swd Username: root Usertype: Sysadmin or SysUser Username: bin Usertype: Sysadmin or SysUser Username: daemon Usertype: Sysadmin or SysUser Username: adm Usertype: Sysadmin or SysUser Username: lp Usertype: Sysadmin or SysUser Username: <span style="color:#dd4a68">sync</span> Usertype: Sysadmin or SysUser Username: <span style="color:#dd4a68">shutdown</span> Usertype: Sysadmin or SysUser Username: halt Usertype: Sysadmin or SysUser Username: mail Usertype: Sysadmin or SysUser Username: operator Usertype: Sysadmin or SysUser Username: games Usertype: Sysadmin or SysUser Username: <span style="color:#dd4a68">ftp</span> Usertype: Sysadmin or SysUser Username: nobody Usertype: Sysadmin or SysUser Username: systemd-bus-proxy Usertype: Sysadmin or SysUser Username: systemd-network Usertype: Sysadmin or SysUser Username: dbus Usertype: Sysadmin or SysUser Username: polkitd Usertype: Sysadmin or SysUser Username: tss Usertype: Sysadmin or SysUser Username: postfix Usertype: Sysadmin or SysUser Username: sshd Usertype: Sysadmin or SysUser Username: tab Usertype: Common User Username: geoclue Usertype: Sysadmin or SysUser Username: apache Usertype: Sysadmin or SysUser Username: centos Usertype: Common User</code></span></span></span>?
顯示以"/bin/bash"為默認(rèn)shell的用戶(hù)的用戶(hù)名:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '{if($NF~/\/bin\/bash$/) print $1}' /etc/passwd</span> root tab centos或者: <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd</span> root tab centos</code></span></span></span>這里分別結(jié)合了模式匹配符或比較操作符來(lái)實(shí)現(xiàn)。
?
以空白字符為分隔符,顯示/etc/fstab文件中字段數(shù)大于等于10的行:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{if(NF>=10) print}' /etc/fstab </span> <span style="color:slategray"># Created by anaconda on Sun Feb 19 10:02:11 2017</span> <span style="color:slategray"># See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info</span>或者: <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'NF>=10' /etc/fstab</span> <span style="color:slategray"># Created by anaconda on Sun Feb 19 10:02:11 2017</span> <span style="color:slategray"># See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info</span></code></span></span></span>?
顯示空間使用率大于等于20%的掛載設(shè)備:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># df -h</span> Filesystem Size Used Avail Use% Mounted on /dev/mapper/cl-root 50G 9.6G 41G 20% / devtmpfs 982M 0 982M 0% /dev tmpfs 993M 0 993M 0% /dev/shm tmpfs 993M 8.7M 984M 1% /run tmpfs 993M 0 993M 0% /sys/fs/cgroup /dev/sda1 1014M 121M 894M 12% /boot /dev/mapper/cl-home 67G 33M 67G 1% /home /dev/sr0 7.8G 7.8G 0 100% /media/cdrom tmpfs 199M 0 199M 0% /run/user/0 <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># </span> <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># df -h | awk -F% '{print $1}' | awk '/\/dev/{if($NF>=20) print $1}'</span> /dev/mapper/cl-root /dev/sr0</code></span></span></span>?
(5) while循環(huán)
語(yǔ)法格式:
while(condition) {statements}
?
循環(huán)條件:
條件為“真”,進(jìn)入循環(huán);
條件為“假”,退出循環(huán).
?
使用場(chǎng)景:
①對(duì)一行內(nèi)的多個(gè)字段逐一進(jìn)行類(lèi)似處理時(shí)使用;
②對(duì)數(shù)組中的各元素逐一處理時(shí)使用.
?
用法示例:
將/etc/grub2.cfg文件中以linux16開(kāi)頭(前面可能有空白符)的行篩選出來(lái),并逐一打印每一行的的各個(gè)字段及其每個(gè)字段的字符數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '/^[[:space:]]*linux16/{i=1; while(i<=NF) {print $i,length($i);</span>i++<span style="color:#999999">}</span><span style="color:#999999">}</span>' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-514.el7.x86_64 30 root<span style="color:#9a6e3a">=</span>/dev/mapper/cl-root 24 ro 2 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/root 17 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/swap 17 rhgb 4 quiet 5 LANG<span style="color:#9a6e3a">=</span>en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-c3d796ed1ad340e09e3d9024cd0350bf 50 root<span style="color:#9a6e3a">=</span>/dev/mapper/cl-root 24 ro 2 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/root 17 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/swap 17 rhgb 4 quiet 5</code></span></span></span>注意:這里調(diào)用了awk的內(nèi)建函數(shù)length()。
?
進(jìn)一步:僅打印字符數(shù)大于7的字段:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '/^[[:space:]]*linux16/{i=1; while(i<=NF) {if(length($i)>7) {pr</span> int <span style="color:#ee9900">$i</span>,length<span style="color:#999999">(</span><span style="color:#ee9900">$i</span><span style="color:#999999">)</span><span style="color:#999999">}</span><span style="color:#999999">;</span> i++<span style="color:#999999">}</span><span style="color:#999999">}</span>' /etc/grub2.cfg /vmlinuz-3.10.0-514.el7.x86_64 30 root<span style="color:#9a6e3a">=</span>/dev/mapper/cl-root 24 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/root 17 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/swap 17 LANG<span style="color:#9a6e3a">=</span>en_US.UTF-8 16 /vmlinuz-0-rescue-c3d796ed1ad340e09e3d9024cd0350bf 50 root<span style="color:#9a6e3a">=</span>/dev/mapper/cl-root 24 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/root 17 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/swap 17</code></span></span></span>?
(6) do-while循環(huán)
語(yǔ)法格式:
do {statements} while(condition)
?
解釋:
無(wú)論是否符合條件,先執(zhí)行一次,而后再根據(jù)condition進(jìn)行判斷。
?
使用場(chǎng)景:
至少需要執(zhí)行一次時(shí)使用。
?
?
(7) for循環(huán)
語(yǔ)法格式:
for(expr1;expr2;expr3) {statements}
?
詳細(xì)格式:
for(variable assignment;condition;iteration process) {for-body}
?
特殊用法:
for(var in array) {for-body}
?
?
功效:能夠遍歷數(shù)組中元素的索引;
注意:其中var為變量,array為數(shù)組名,{for-body}為循環(huán)體。前面提到,awk具有內(nèi)生循環(huán)功能,能自動(dòng)實(shí)現(xiàn)對(duì)文本所有行的遍歷,而這里的for循環(huán)則可實(shí)現(xiàn)每一行的字段間的循環(huán)。
?
用法示例:
還是剛才的例子,將/etc/grub2.cfg文件中以linux16開(kāi)頭(前面可能有空白符)的行篩選出來(lái),并逐一打印每一行的的各個(gè)字段及其每個(gè)字段的字符數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '/^[[:space:]]linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg </span> linux16 7 /vmlinuz-3.10.0-514.el7.x86_64 30 root<span style="color:#9a6e3a">=</span>/dev/mapper/cl-root 24 ro 2 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/root 17 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/swap 17 rhgb 4 quiet 5 LANG<span style="color:#9a6e3a">=</span>en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-c3d796ed1ad340e09e3d9024cd0350bf 50 root<span style="color:#9a6e3a">=</span>/dev/mapper/cl-root 24 ro 2 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/root 17 rd.lvm.lv<span style="color:#9a6e3a">=</span>cl/swap 17 rhgb 4 quiet 5</code></span></span></span>?
(8) switch語(yǔ)句
語(yǔ)法格式:
switch(condition) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; case VALUE3 or /REGEXP3/: statement; default: statement}
?
(9) break和continue
功效:
break [n]:跳出n層循環(huán);
continue:結(jié)束本輪循環(huán)并提前進(jìn)入下一輪循環(huán);
?
(10) next
功效:
next:提前結(jié)束對(duì)本行的處理而直接進(jìn)入下一行。
?
next和continue的區(qū)別:
continue是用于控制行內(nèi)字段間的跳轉(zhuǎn)的,而next是用于控制awk的內(nèi)生循環(huán)以實(shí)現(xiàn)在行間的跳轉(zhuǎn),從而提前進(jìn)入下一行處理。
?
示例:
顯示uid為偶數(shù)的用戶(hù)的用戶(hù)名和uid
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd</span> root 0 daemon 2 lp 4 <span style="color:#dd4a68">shutdown</span> 6 mail 8 games 12 <span style="color:#dd4a68">ftp</span> 14 systemd-network 192 polkitd 998 sshd 74 tab 1000 apache 48</code></span></span></span>?
(11) 數(shù)組(array)
定義數(shù)組:
array[index-expression]
?
注意:array為自定義的數(shù)組名,index-expression為索引表達(dá)式,awk支持索引數(shù)組和關(guān)聯(lián)數(shù)組,而在awk中關(guān)聯(lián)數(shù)組更為常用。
?
刪除數(shù)組:
delete array[index-expression]:刪除數(shù)組中的某元素;
delete array:刪除數(shù)組.
?
要點(diǎn):
①awk支持關(guān)聯(lián)數(shù)組,可使用任何字符串;字符串要使用雙引號(hào);
②如果數(shù)組中的某個(gè)元素事先不存在,在引用時(shí),awk會(huì)自動(dòng)創(chuàng)建這個(gè)元素,并將其值初始化為“空串”;而如果引用一個(gè)事先不存在的數(shù)組元素來(lái)做數(shù)值運(yùn)算時(shí),則會(huì)自動(dòng)將該元素賦值為0.
③若要判斷數(shù)組中是否存在某元素,不可以直接引用,因?yàn)橐灰镁蜁?huì)自動(dòng)創(chuàng)建(一創(chuàng)建就相當(dāng)于存在了),而應(yīng)該使用"index in array"格式來(lái)做判斷。
④若要遍歷整個(gè)數(shù)組中的元素,則要使用for循環(huán):for(var in array) {for-body}.
?
用法示例:
創(chuàng)建一個(gè)關(guān)聯(lián)數(shù)組,數(shù)組第一個(gè)元素的索引為"mon",值為"Monday",第二個(gè)元素的索引為"tue",值為"Tuesday";創(chuàng)建之后顯示指定的數(shù)組元素:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print</span>weekdays<span style="color:#999999">[</span><span style="color:#669900">"mon"</span><span style="color:#999999">]</span><span style="color:#999999">}</span>' Monday</code></span></span></span>當(dāng)不需要對(duì)文件進(jìn)行處理時(shí),可在前面帶上"BEGIN"。
?
進(jìn)一步:遍歷顯示數(shù)組中的所有元素:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i</span><span style="color:#0077aa">in</span> weekdays<span style="color:#999999">)</span> <span style="color:#999999">{</span>print weekdays<span style="color:#999999">[</span>i<span style="color:#999999">]</span><span style="color:#999999">}</span><span style="color:#999999">}</span>' Tuesday Monday</code></span></span></span>使用for的特殊用法去遍歷數(shù)組中的每個(gè)元素時(shí),例如此處,awk會(huì)將數(shù)組'weekdays'中的每個(gè)元素的索引賦值給變量i,而不是直接將數(shù)組的元素直接賦值給變量i。此處遍歷的順序可能和我們預(yù)想的不一致。
?
判斷數(shù)組中的某個(gè)元素是否存在:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{testarray["a"]="hello"; testarray["b"]="hi"; if("a" in t</span> estarray<span style="color:#999999">)</span> <span style="color:#999999">{</span>print <span style="color:#669900">"exist."</span><span style="color:#999999">}</span> <span style="color:#0077aa">else</span> print <span style="color:#669900">"not exist."</span> <span style="color:#999999">}</span><span style="color:#669900">' exist. [root@localhost ~]# [root@localhost ~]# awk '</span>BEGIN<span style="color:#999999">{</span>testarray<span style="color:#999999">[</span><span style="color:#669900">"a"</span><span style="color:#999999">]</span><span style="color:#9a6e3a">=</span><span style="color:#669900">"hello"</span><span style="color:#999999">;</span> testarray<span style="color:#999999">[</span><span style="color:#669900">"b"</span><span style="color:#999999">]</span><span style="color:#9a6e3a">=</span><span style="color:#669900">"hi"</span><span style="color:#999999">;</span> if<span style="color:#999999">(</span><span style="color:#669900">"c"</span> <span style="color:#0077aa">in</span> t estarray<span style="color:#999999">)</span> <span style="color:#999999">{</span>print <span style="color:#669900">"exist."</span><span style="color:#999999">}</span> <span style="color:#0077aa">else</span> print <span style="color:#669900">"not exist."</span> <span style="color:#999999">}</span>' not exist.</code></span></span></span>?
根據(jù)前面提到,如果我們要引用數(shù)組中的某元素,而這個(gè)元素事先是不存在的,那么當(dāng)我們引用時(shí)awk會(huì)自動(dòng)創(chuàng)建這個(gè)元素,并且初始化為“空串”,當(dāng)然了,如果我們直接把這個(gè)事先不存在的數(shù)組元素拿去做運(yùn)算,則會(huì)自動(dòng)初始化為“0”。在生產(chǎn)環(huán)境中,利用這一特性,我們可以實(shí)現(xiàn)一個(gè)通用而且非常實(shí)用的功能:當(dāng)我們需要統(tǒng)計(jì)在文本中某些字符串各自分別出現(xiàn)的次數(shù)時(shí),可以直接把這些字符串分別作為一個(gè)數(shù)組的索引,并且使得在各個(gè)要統(tǒng)計(jì)的字符串每次出現(xiàn)時(shí),以該字符串作為索引的數(shù)組元素自動(dòng)加1.
說(shuō)起來(lái)有點(diǎn)抽象,接下來(lái)我們看一看如何利用這一特性:
?
用netstat命令查看當(dāng)前網(wǎng)路連接狀態(tài):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># netstat -tan</span> Active Internet connections <span style="color:#999999">(</span>servers and established<span style="color:#999999">)</span> Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp 0 0 10.10.10.140:22 10.10.10.1:52641 ESTABLISHED tcp 0 52 10.10.10.140:22 10.10.10.1:51926 ESTABLISHED tcp 0 0 10.10.10.140:51816 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:51818 10.10.10.140:80 TIME_WAIT tcp 0 0 10.10.10.140:22 10.10.10.1:52640 ESTABLISHED tcp 0 0 10.10.10.140:51814 10.10.10.140:80 TIME_WAIT tcp6 0 0 :::80 :::* LISTEN tcp6 0 0 :::22 :::* LISTEN tcp6 0 0 ::1:25 :::* LISTEN tcp6 0 0 10.10.10.140:80 10.10.10.140:49844 TIME_WAIT tcp6 0 0 10.10.10.140:80 10.10.10.140:50304 TIME_WAIT tcp6 0 0 10.10.10.140:80 10.10.10.140:49828 TIME_WAIT</code></span></span></span>?
統(tǒng)計(jì)netstat命令執(zhí)行結(jié)果中tcp連接的各個(gè)狀態(tài)的個(gè)數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># netstat -tan | awk '/tcp\>/{state[$NF]++}END{for(i in state) print i,state[i]}'</span> LISTEN 2 ESTABLISHED 3 TIME_WAIT 3</code></span></span></span>命令解釋:
這里首先錨定匹配以'tcp'開(kāi)頭的行;接著把匹配到的每一行的最后一個(gè)字段(即狀態(tài))賦值為數(shù)組state的索引,這里因?yàn)槭孪萻tate[$NF]不存在,所以awk會(huì)自動(dòng)創(chuàng)建之,并將對(duì)應(yīng)的數(shù)組元素初始化為“空串”;但又因?yàn)檫@里直接將數(shù)組元素用于自增運(yùn)算,因此初始值為0,以用于做自增運(yùn)算,而我們要統(tǒng)計(jì)的各個(gè)狀態(tài)每出現(xiàn)一次,就會(huì)自動(dòng)把這個(gè)狀態(tài)所對(duì)應(yīng)的數(shù)組state的索引對(duì)應(yīng)的元素值加1.
最后我們只需要用for循環(huán)遍歷一次數(shù)組state的索引,并顯示索引(這里"索引"即為"狀態(tài)")以及對(duì)應(yīng)的元素值(即各個(gè)狀態(tài)分別出現(xiàn)的次數(shù))。
?
此外,在生產(chǎn)環(huán)境中通常使用ss命令結(jié)合awk工具來(lái)做統(tǒng)計(jì),這樣執(zhí)行性能更佳。
?
統(tǒng)計(jì)/var/log/httpd/access_log日志文件中各個(gè)ip地址從本地Web服務(wù)器獲取資源的次數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '{ip[$1]++}END{for(i in ip) print i,ip[i]}' /var/log/httpd/acce</span> ss_log 10.10.10.138 1014 10.10.10.1 221 10.10.10.139 4024 10.10.10.140 4000</code></span></span></span>?
查看/etc/fstab文件內(nèi)容:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># cat /etc/fstab </span><span style="color:slategray">#</span> <span style="color:slategray"># /etc/fstab</span> <span style="color:slategray"># Created by anaconda on Tue Oct 4 09:06:12 2016</span> <span style="color:slategray">#</span> <span style="color:slategray"># Accessible filesystems, by reference, are maintained under '/dev/disk'</span> <span style="color:slategray"># See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info</span> <span style="color:slategray">#</span> UUID<span style="color:#9a6e3a">=</span>60eb0d1c-9834-4348-9a79-2f91983a8ede / ext4 defaults 1 1 UUID<span style="color:#9a6e3a">=</span>3995456f-a3e9-4b69-a0de-0fd48068da39 /boot ext4 defaults 1 2 UUID<span style="color:#9a6e3a">=</span>01d24b59-eee4-472e-9985-ef44fd5e059c swap swap defaults 0 0 tmpfs /dev/shm tmpfs defaults 0 0 devpts /dev/pts devpts gid<span style="color:#9a6e3a">=</span>5,mode<span style="color:#9a6e3a">=</span>620 0 0 sysfs /sys sysfs defaults 0 0 proc /proc proc defaults 0 0 /dev/sr0 /media/cd iso9660 defaults 1 2</code></span></span></span>統(tǒng)計(jì)/etc/fstab文件中每個(gè)文件系統(tǒng)類(lèi)型出現(xiàn)的次數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk '/^UUID/{fs[$3]++}END{for(i in fs) print i,fs[i]}' /etc/fstab </span> swap 1 ext4 2</code></span></span></span>?
統(tǒng)計(jì)指定文件中每個(gè)單詞出現(xiàn)的次數(shù),并統(tǒng)計(jì)出使用次數(shù)最多的英語(yǔ)單詞及其出現(xiàn)次數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># cat test.txt //打開(kāi)一篇英語(yǔ)文章;</span> I am too busy now. The life is different <span style="color:#0077aa">in</span> the past and now. Let me tell you about my life. In the past,I didn<span style="color:#669900">'t study or do some things. I always played with my parents. My dad often took me to go to the zoo. That was really interesting! But now as a student, I have to stay in school all day. At home, I have too much homework to do.So I have to do homework. Time is flies. I miss past. I hope it back soon. [root@localhost ~]# [root@localhost ~]# [root@localhost ~]# awk '</span><span style="color:#999999">{</span>for<span style="color:#999999">(</span>i<span style="color:#9a6e3a">=</span>1<span style="color:#999999">;</span>i<span style="color:#9a6e3a"><=</span>NF<span style="color:#999999">;</span>i++<span style="color:#999999">)</span> <span style="color:#999999">{</span>count<span style="color:#999999">[</span><span style="color:#ee9900">$i</span><span style="color:#999999">]</span>++<span style="color:#999999">}</span><span style="color:#999999">}</span>END<span style="color:#999999">{</span>for<span style="color:#999999">(</span>i <span style="color:#0077aa">in</span> count<span style="color:#999999">)</span> <span style="color:#999999">{</span>print i,c ount<span style="color:#999999">[</span>i<span style="color:#999999">]</span><span style="color:#999999">}</span><span style="color:#999999">}</span>' test.txt <span style="color:#9a6e3a">|</span> <span style="color:#dd4a68">sort</span> -r -n -k2 <span style="color:#9a6e3a">|</span> <span style="color:#dd4a68">head</span> -5 I 7 to 5 the 3 have 3 too 2</code></span></span></span>?
(12) 函數(shù)
awk的函數(shù)有兩種類(lèi)型,一種是內(nèi)置函數(shù),一種是自定義函數(shù)。這里我們介紹一下awk的內(nèi)置函數(shù)吧!
?
數(shù)值處理:
rand():返回0和1之間的一個(gè)隨機(jī)數(shù).
?
實(shí)例:
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># awk 'BEGIN{print rand()}'</span> 0.237788</code></span></span></span>注意:只有第一次取得的數(shù)是隨機(jī)的,之后會(huì)一直沿用第一次取得的值。
?
字符串處理:
length():返回指定字符串的長(zhǎng)度;
sub(r,s,[t]):以r表示的模式去查找t所表示的字符串中匹配到的內(nèi)容,并將其第一次匹配到的內(nèi)容替換為s所表示的內(nèi)容。
gsub(r,s,[t]):以r表示的模式去查找t所表示的字符串中匹配到的內(nèi)容,并將其第所有匹配到的內(nèi)容替換為s所表示的內(nèi)容。
split(s,a[,r]):以r為分隔符切割字符s,并將其切割后的結(jié)果保存至a所表示的數(shù)組中。
?
注意:這里a所表示的數(shù)組的索引從1開(kāi)始,而字段的各個(gè)切片分別保存至索引1,2,3,...中。
?
實(shí)例:
統(tǒng)計(jì)所有客戶(hù)端IP地址及其出現(xiàn)的次數(shù):
<span style="color:#333333"><span style="color:#333333"><span style="color:black"><code class="language-bash"><span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># netstat -tan</span> Active Internet connections <span style="color:#999999">(</span>servers and established<span style="color:#999999">)</span> Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp 0 52 10.10.10.140:22 10.10.10.1:51134 ESTABLISHED tcp 0 0 10.10.10.140:22 10.10.10.1:51531 TIME_WAIT tcp6 0 0 :::80 :::* LISTEN tcp6 0 0 :::22 :::* LISTEN tcp6 0 0 ::1:25 :::* LISTEN <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># </span> <span style="color:#999999">[</span>root@localhost ~<span style="color:#999999">]</span><span style="color:slategray"># netstat -tan | awk '/^tcp\>/{split($5,ip,":"); count[ip[1]]++}END{for</span> <span style="color:#999999">(</span>i <span style="color:#0077aa">in</span> count<span style="color:#999999">)</span> <span style="color:#999999">{</span>print i,count<span style="color:#999999">[</span>i<span style="color:#999999">]</span><span style="color:#999999">}</span><span style="color:#999999">}</span>' 10.10.10.1 1 0.0.0.0 2</code></span></span></span>命令解釋:
首先awk會(huì)匹配以tcp開(kāi)頭的行,接著split()函數(shù)將模式(/^tcp\>/)匹配到的行的第5個(gè)字段以":"作為分隔符做切分,各個(gè)切片依次保存至ip所表示的數(shù)組中;而這里split()函數(shù)參數(shù)中,ip所表示的數(shù)組的索引是從1開(kāi)始計(jì)數(shù)的,因此第5個(gè)字段":"左側(cè)的ip地址保存至ip[1],":"右側(cè)的端口號(hào)保存至ip[2];這里我們需要統(tǒng)計(jì)的是ip地址,所以按照前面幾個(gè)例題的思路,這里使用了數(shù)組元素嵌套的方法將ip[1]的值作為數(shù)組count的索引。
文章來(lái)源:http://blog.51cto.com/xuweitao/1905269
總結(jié)
- 上一篇: 时间戳转时间到秒
- 下一篇: piranha启动报错