天天看點

awk的使用---業務需求

awk是按照流來處理的,是以處理1-5G的文本資料相對還是可以的!

求和

awk -F : -v sum=0 '{sum+=$3} END{print sum}' /etc/passwd

或者 

awk -F :   '{sum+=$3} END{print sum}' /etc/passwd

預設變量為0

規定日志格式

$17 為domainname

$19 為request

$21 為響應狀态碼

應用1: 比對統計F5日志中,含有某個域名的數量

可以按照以下方法來套

<code>[root@CentOS-6-121 scripts]</code><code># awk -F:  '$1=="root" {print $0}' /etc/passwd | wc -l</code>

<code>1</code>

對以上進行改版,因為統計的時候利用了wc -l 進行了,現在不需要wc -l ,awk完成統計

<code>[root@CentOS-6-121 scripts]</code><code># awk -F:  -v n=0 '{if($1=="root") n++;}  END{print n}' /etc/passwd </code>

-v 可以指定變量,在 awk ''中利用變量的時候直接使用,不需要"$n" 這個地方要差別shell

注意: 以下語句,預設不指定n變量的時候,雖然可以出結果,是因為在n++的時候會預設設定n為0,但是這樣會出現bug,當沒有比對的時候,去大于n的時候就不是0而是空

<code>[root@CentOS-6-121 scripts]</code><code># awk -F:   '{if($1=="root") n++;}  END{print n}' /etc/passwd </code>

bug:

<code>[root@CentOS-6-121 scripts]</code><code># awk -F:   '{if($1=="rooot") n++;}  END{print n}' /etc/passwd </code>

<code>[root@CentOS-6-121 scripts]</code><code>#</code>

應用2: 使用shell中的變量和定義多變量 和邏輯運算符

&amp;&amp; 邏輯與

|| 邏輯或

! 否

~ 比對字元串  !~  不比對後面更正規表達式

-v key1=value1 -v key2-values

引用變量兩種方式

1

name="John"

  -v myname=$name '{print myname}'

2 在awk中我們可以通過“’$變量名’”的方式讀取sell scrpit程式中的變量。

awk '{print $1,$2,"'$name'"}'  flil

原型:

awk -v t=0 -v domain="$domain" -v request="/main/detail" -v code=500  '$17==domain &amp;&amp; $19 ~ request &amp;&amp; $21 ==code {t++} END{print t}' access.log

測試語句:

<code>[root@CentOS-6-121 scripts]</code><code># awk -F: '$1=="root" &amp;&amp; $3==0 {print $0}' /etc/passwd</code>

<code>root:x:0:0:root:</code><code>/root</code><code>:</code><code>/bin/bash</code>

awk -F:  '$1 =="root" || $1=="nobody" {print $1 "\t"$3}' /etc/passwd

nobody-2

root0

awk -F:  '$NF != "/bin/bash"  {print $1 "\t" $NF}' /etc/passwd

比對:

awk '$NF !~ "/sbin/no*" {print $1" " $3}' /etc/passwd 

awk '$NF !~ /sbin\/no*/ {print $1" " $3}' /etc/passwd  (使用 ~ /express/ 是man awk 中正規的寫法)

注意:

判斷比對的方法:

 1)$n~正規表達式

 2)if($n~正則表示式) print $

如果你的awk中使用了 BEGIN語句,就一定要使用 if 不能使用模式比對,否則報錯

如:

報錯:

<code>[root@CentOS-6-121 scripts]</code><code># awk -F: '$1=="root" &amp;&amp; $3==0 BEGIN{n=0} {n++} END{print n}' /etc/passwd</code>

awk: $1=="root" &amp;&amp; $3==0 BEGIN{n=0} {t++} END{print t}

awk:                     ^ syntax error

改為:

<code>[root@CentOS-6-121 scripts]</code><code># awk -F: 'BEGIN{n=0} {if($1 =="root" &amp;&amp; $3==0)n++} END{print n}' /etc/passwd</code>

<code>使用變量:</code>

<code>[root@master ~]</code><code># n=1000</code>

<code>[root@master ~]</code><code># awk -v n=$n -F: '$3==n {print $1" "$3}' /etc/passwd</code>

<code>elasticsearch 1000</code>

應用3: awk中的數組

<code>awk</code> <code>-F : </code><code>'{bash_array[$NF]++} END {for(i in bash_array) {print i,bash_array[i]}}'</code> <code>/etc/passwd</code>

/bin/nologin 1

/sbin/shutdown 1

/bin/false 1

/bin/bash 11

/sbin/nologin 28

/sbin/halt 1

/bin/sync 1

3 指定域名的

<code>[root@shnh-bak001 f5-log]$ </code><code>awk</code> <code>'$17 ==</code><code>"gold.dianpingfang.com"</code> <code>{++domain[$21]} END {</code><code>for</code><code>(k</code>

<code>in</code> <code>domain) print k,domain[k]}' access.log</code>

 2

200 4498

301 2

500 15

302 321

304 2

應用四:統計目錄下的一部分目錄的資料大小

<code>du</code> <code>-s stu* | </code><code>awk</code> <code>'{sum=sum+$1} END{print sum}'</code>

資料庫的連接配接情況

<code>netstat</code> <code>-tanp |</code><code>awk</code> <code>'/3306/ {print $5}'</code>  <code>|</code><code>awk</code> <code>-F </code><code>":"</code> <code>'{a[$1]++}END{for (i in a) print a[i],i}'</code>  <code>|</code><code>sort</code> <code>-nr</code>

應用五:行範圍指定

AWK 的比對模式種類:

 Patterns

       AWK patterns may be one of the following:

              BEGIN

              END

              /regular expression/

              relational expression

              pattern &amp;&amp; pattern

              pattern || pattern

              pattern ? pattern : pattern

              (pattern)

              ! pattern

              pattern1, pattern2

awk -F : '{print $NF":"$2":"$3":"$4":"$5":"$6":"$1 &gt; "/tmp/oldboy/passwd"}' /tmp/oldboy/passwd

列印第2、3、4、5行

sed -n "2,5p" /etc/passwd

awk "NR==2,NR==5" /etc/passwd

awk "NR&gt;1&amp;&amp;NR&lt;6" /etc/passwd

cat /etc/passwd | head -5 | tail -4

執行個體:

 awk -F: 'NR==2,NR==5 {print $1}' /etc/passwd

awk -F: 'NR&gt;1 &amp;&amp; NR&lt;6{print $1}' /etc/passwd 

案例6: 列印awk第一次比對到的關鍵字,之後的所有行!

分兩步,第一找出第一次比對的行,比對nobody賬号

<code>awk</code> <code>-F </code><code>":"</code> <code>'{if($1 ~ "nobody") print NR;}'</code> <code>passwd</code>

15

25

思考,如何隻比對到一次後,就退出awk繼續向下比對而直接退出查找。

改良:

<code>awk</code> <code>-F </code><code>":"</code> <code>'{if($1== "nobody") {print NR; exit 0}}'</code> <code>passwd</code>

第二: 列印第15行之後的所有行

<code>awk</code> <code>-F </code><code>":"</code> <code>'{if(NR &gt; 15) print $0;}'</code> <code>passwd</code>

或者(以下行範圍更适用)

awk -F: 'NR&gt;15{print $1}' /etc/passwd     

可以提高難道綜合成一條awk語句

<code>awk</code> <code>-F </code><code>":"</code> <code>'{if($1== "nobody") {a=NR}} {if(NR&gt;a &amp;&amp; a!=0) print $0}'</code> <code>passwd</code>

為什麼要做一個a!=0 的條件,因為沒有比對到nobody的時候,未定義指派過的變量再awk中預設值為0。

案例七: awk中調用系統指令

<code>awk</code> <code>-F </code><code>":"</code> <code>'{if($1== "nobody") {system("echo this is noboy user")}} '</code> <code>passwd</code>

或者: $1=="root" 字元串一定要用引号引起來,不然在awk裡面就是變量拉

awk -F ":" '$1=="root" {system("echo this is noboy user")} ' /etc/passwd

案例7: awk多分隔符切,分隔符為[ 

rabbitmq的叢集狀态 partitions行  {partitions,[]}]  如果[] 中有内容i表示叢集不正常。

<code>if</code> <code>[ </code><code>"x"</code> <code>!= </code><code>"x$(sudo /usr/sbin/rabbitmqctl cluster_status |grep partitions |awk -F '[\\[\\]]'  '{print $2}')"</code> <code>];</code><code>then</code> <code>echo</code> <code>0;</code><code>else</code> <code>echo</code> <code>1;</code><code>fi</code>

案例8:  統計nf(iptables 跟蹤連結清單中 各協定的數量)

<code>awk</code> <code>'{a[$3]++ } END{for (k in a) print k,a[k]}'</code> <code>/proc/net/nf_conntrack</code>

tcp 11

udp 26

icmp 1

案例7. 使用split内置函數進行分割

<code>tac  haproxy.log  | </code><code>awk</code> <code>'{</code>

<code>                                        </code><code>split</code><code>($6,a,</code><code>":"</code><code>)</code>

<code>                                        </code><code>if</code><code>(a[1]~</code><code>"05/Mar/2017"</code><code>){ </code>

<code>                                            </code><code>print $0</code>

<code>                                        </code><code>}</code>

<code>                                        </code><code>if</code><code>(a[1]~</code><code>"04/Mar/2017"</code><code>){</code><code>exit</code><code>}</code>

<code>                                </code><code>}' &gt;&gt; .</code><code>/a_access</code><code>.log </code>

<code>exit</code>

案例8: 列印比對的行并 輸出檔案名

awk '/root/{print FILENAME "-----"$0}' /etc/passwd

#FILENAME 是預設變量,或者使用grep實作

grep -H root /etc/passwd

#-H 是顯示檔案名在比對的行前面

内置函數的使用

split的用法:

一、split 初始化和類型強制 

       awk的内建函數split允許你把一個字元串分隔為單詞并存儲在數組中。你可以自己定義域分隔符或者使用現在FS(域分隔符)的值。

格式:

   split (string, array, field separator)

    split (string, array)  --&gt;如果第三個參數沒有提供,awk就預設使用目前FS值。

例2:計算指定範圍内的和(計算每個人1月份的工資之和)

<code>[root</code><code>@test</code> <code>~]</code><code># cat test.txt</code>

<code>Tom    </code><code>2012</code><code>-</code><code>12</code><code>-</code><code>11</code>      <code>car     </code><code>53000</code>

<code>John   </code><code>2013</code><code>-</code><code>01</code><code>-</code><code>13</code>      <code>bike    </code><code>41000</code>

<code>vivi    </code><code>2013</code><code>-</code><code>01</code><code>-</code><code>18</code>      <code>car     </code><code>42800</code>

<code>Tom    </code><code>2013</code><code>-</code><code>01</code><code>-</code><code>20</code>      <code>car     </code><code>32500</code>

<code>John   </code><code>2013</code><code>-</code><code>01</code><code>-</code><code>28</code>      <code>bike    </code><code>63500</code>

<code>[root</code><code>@test</code> <code>~]</code><code># awk '{split($2,a,"-");if(a[2]==01){b[$1]+=$4}}END{for(i in b)print i,b[i]}' test.txt  </code>

<code>vivi </code><code>2800</code>

<code>Tom2500</code>

<code>John4500</code>

2. gsub的函數

替換正規表達式的内容

 gsub(r, s [, t])        For each substring matching the regular expression r in the string  t,sub-stitute  the  string s。

t字元串中比對r正則的替換成s字元串。

r: 正規表達式

s:字元串

t,如果省略就是 $0.

awk '$0 ~ /6.8/ {gsub("6.8", "6.6", $0); print $0}' /etc/issue

将最後一行為nologin的替換成 /bin/bash

 awk -F: '{gsub(".*nologin","/bin/bash",$NF) ;print $NF}' /etc/passwd

3.  length()函數

length([s]) 

傳回字元串的長度,如果s沒有提供,預設是$0。

[root@cuizhiliang ~]# cat /etc/issue |awk '{print length($2)}'                               

7

2

#分析文本中每行的字元大小 找到很長的那一行

[root@cuizhiliang ~]# cat /etc/issue |awk '{print length()}'    

26

18

4 文本處理 大小寫轉換函數 toupper(string), tolower(string)

awk -F: 'NR==1,NR==2{print toupper($NF)}' /etc/passwd 

/BIN/BASH

/SBIN/NOLOGIN

5 index函數

index(s, t)  

傳回t中的字元串出現在s中的開始位置.從1開始的位置。若沒有則傳回0

Returns the index of the string t in the string s, or 0 if t is not present.

(This implies that character indices start at one.)

[root@master ~]# awk 'BEGIN{print index("98765432123","23")}'

10

6 system 調用系統指令

重要的是調用系統給的指令的時候 參數适用awk的field字段。

head dfs.log | awk '{system("./purge_squid_url.sh " ""$0"")}'

arp -n|awk '/^[1-9]/{system("echo "$1)}'

arp -n| awk '/^[1-9]/{system("echo " ""$1"")}'

删除所有的arp

arp -n|awk '/^[1-9]/{system("arp -d "$1)}'

本文轉自殘劍部落格51CTO部落格,原文連結http://blog.51cto.com/cuidehua/1771599如需轉載請自行聯系原作者

cuizhiliang