awk學習筆記之實用案例

案例1:插入幾個新字段
在”a b c d”的b後面插入3個字段e f g
思路:在b後面插入e f g相當於在c前面插入e f g
在這裏插入圖片描述
Note:修改字段(會反饋給$0,相當於修改了$0)或者修改$0後會重建$0(根據OFS重建$0),OFS的默認值是一個空格。

案列2:格式化空白
移除每行的前綴、後綴、空白,並將各部分左對齊
原始文檔格式
在這裏插入圖片描述
直接給字段賦原值就可以格式化文本,因爲更改字段會以OFS重建$0

在這裏插入圖片描述
上面的方法是以單個空格隔開每個字段,但是我們想用製表符隔開每個字段的話,因該如下操作
在這裏插入圖片描述
案列3:篩選IPv4地址
從ifconfig命令的結果中篩選出除了lo網卡外的所有IPv4地址
方法1:

#ifconfig | awk '/inet / && !($2 ~ /^127/){print $2}'

在這裏插入圖片描述
方法2:
按段落讀取,默認情況下awk是以行讀取,所以需要修改輸入分割控制符(RS)
RS="":按段落讀取
RS="\0":一次性讀取所有數據,但有些特殊文件中包含了空字符\0
RS="^$":真正的一次性讀取所有數據,因爲非空文件不可能匹配成功
RS="\n+":按行讀取,但忽略所有空行

#ifconfig | awk 'BEGIN{RS=""}{print}'

在這裏插入圖片描述
只輸出第一段落

#ifconfig |awk 'BEGIN{RS=""}NR==1{print}'

在這裏插入圖片描述
取得ip地址,需要知道其在第幾個字段,字段默認是以空格劃分的,所以數一下ip在第幾個字段,注意換行符也是空格,所以ip在地6個字段

#ifconfig |awk 'BEGIN{RS=""}NR==1{print $6}'

在這裏插入圖片描述
但是以上取法不是很好,會受到網卡的排列順序影響,進一步改進,將lo開頭的網卡排除在外即可

#ifconfig |awk 'BEGIN{RS=""}!/^lo:/{print $6}'

在這裏插入圖片描述
方法3:
取出段後再按行劃分字段(以換行符劃分)

#ifconfig |awk 'BEGIN{RS="";FS="\n"}!/^lo:/{$0=$2;FS=" ";$0=$0;print $2}'

在這裏插入圖片描述
案例4:讀取.repo配置文件中的某段
本例選取yum源的配置文件CentOS-Base.repo作爲實驗素材,原文如下:

# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the 
# remarked out baseurl= line instead.
#
#
 
[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/os/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#released updates 
[updates]
name=CentOS-$releasever - Updates - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/updates/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/updates/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/extras/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/extras/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/centosplus/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/centosplus/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
 
#contrib - packages by Centos Users
[contrib]
name=CentOS-$releasever - Contrib - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/contrib/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/contrib/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/contrib/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

假設現在要取出[base]段的文本,首先創建一個名爲test1.awk的文件,然後編寫腳本

[root@localhost yum.repos.d]# touch test1.awk
[root@localhost yum.repos.d]# ls
CentOS-Base.repo  CentOS-SCLo-scl-rh.repo  test1.awk

正則中需要轉義的特殊字符如下:

$     匹配輸入字符串的結尾位置。如果設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 ‘\n' 或 ‘\r'。要匹配 $ 字符本身,請使用 \$

( )    標記一個子表達式的開始和結束位置。子表達式可以獲取供以後使用。要匹配這些字符,請使用 \( 和 \)

*      匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 \*

+      匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 \+

.      匹配除換行符 \n之外的任何單字符。要匹配 .,請使用 \

[ ]    標記一箇中括號表達式的開始。要匹配 [,請使用 \[

?      匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 \?

\      將下一個字符標記爲或特殊字符、或原義字符、或向後引用、或八進制轉義符。例如, ‘n' 匹配字符 ‘n'。'\n' 匹配換行符。序列 ‘\\' 匹配 “\”,而 ‘\(' 則匹配 “(”

^      匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符本身,請使用 \^。

{ }    標記限定符表達式的開始。要匹配 {,請使用 \{

|      指明兩項之間的一個選擇。要匹配 |,請使用 \|
#/\[base\]/      字符不確定的情況下使用這種方法
#字符確定的情況下使用index
#對於確定字符串可以使用index進行搜索,在$0中進行搜索,當其中的字串存在[base]時候,返回其索引位,索引位是大於零的,從1開始
index($0,"[base]"){              
print
while( (getline var) >0 ){
if (var ~ /\[.*\]/){
  exit
	}
print var
  }
}
#getline()的說明
#當getline()的返回值大於零時,表示已經取到數據
#當getline()的返回值等於零時,表示遇到結尾EOF,也就是沒有讀取到符合條件的字符
#當getline()的返回值小於零時,表示讀取報錯,沒有權限等
#var ~ /\[.*\]/  如果匹配到其他的就退出

在這裏插入圖片描述
在這裏插入圖片描述

案列5:根據某個字段去重
去掉 uid=xxx 重複的行
可以根據第一次出現去重,也可以根據最後一次出現去重

2019-01-13_12:00_index?uid=123
2019-01-13_13:00_index?uid=123
2019-01-13_14:00_index?uid=333
2019-01-13_15:00_index?uid=9710
2019-01-14_12:00_index?uid=123
2019-01-14_13:00_index?uid=123
2019-01-15_14:00_index?uid=333
2019-01-16_15:00_index?uid=9710

先將每一行以問號爲界限劃分爲兩個字段,然後將$2放入數組arr,統計$2出現的次數,如果只出現一次則輸出,如出現多次只輸出第一次出現的值

#awk -F "?" '{arr[$2]=arr[$2]+1;if(arr[$2]==1){print}}' test2.txt

也可以改爲自增運算:

#awk -F "?" '{arr[$2]++;if(arr[$2]==1){print}}' test2.txt
或者
#awk -F "?" '{++arr[$2];if(arr[$2]==1){print}}' test2.txt

更進一步改進:

#awk -F "?" '!arr[$2]++{print}' test2.txt    
#當第一次讀取到時arr[0]返回0,取反後返回爲真,則輸出;第二次讀取到時,返回1,取反後爲假,則不輸出
#而且print也可以省略,因爲awk默認會輸出
#awk -F "?" '!arr[$2]++' test2.txt 

在這裏插入圖片描述

案列6:用awk數組做次數統計
(1)次數統計
統計的素材如下:

portmapper
portmapper
portmapper
portmapper
portmapper
portmapper
status
status
mountd
mountd
mountd
mountd
mountd
mountd
nfs
nfs
nfs_acl
nfs
nfs
nfs_acl
nlockmgr
nlockmgr
nlockmgr
nlockmgr
nlockmgr
#awk '{arr[$0]++}END{OFS="\t";for(i in arr){print arr[i],i}}' test3.txt

在這裏插入圖片描述
(2)統計TCP連接狀態數量

#netstat -tnap

狀態state字段是$6,將其放入數組中進行統計

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 192.168.33.99:25        0.0.0.0:*               LISTEN      2388/master         
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      2388/master         
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN      3313/sshd: root@pts 
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      1114/redis-server 1 
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      1726/rpcbind        
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1595/sshd           
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      2957/cupsd          
tcp        0      0 0.0.0.0:52856           0.0.0.0:*               LISTEN      1816/rpc.statd      
tcp        0      0 192.168.33.99:22        192.168.33.102:52093    ESTABLISHED 3313/sshd: root@pts 
tcp6       0      0 ::1:25                  :::*                    LISTEN      2388/master         
tcp6       0      0 ::1:6010                :::*                    LISTEN      3313/sshd: root@pts 
tcp6       0      0 :::42719                :::*                    LISTEN      1816/rpc.statd      
tcp6       0      0 :::111                  :::*                    LISTEN      1726/rpcbind        
tcp6       0      0 :::22                   :::*                    LISTEN      1595/sshd           
tcp6       0      0 ::1:631                 :::*                    LISTEN      2957/cupsd          
#netstat -nat|awk '/^tcp /{arr[$6]++}END{for(state in arr){print arr[state]":"state}}'

在這裏插入圖片描述

#netstat -nat | grep  'tcp' | awk '{print $6}'|sort | uniq -c

在這裏插入圖片描述
案列6:統計日誌中特定條件的字段出現的次數

(1)統計日誌中非200狀態碼的IP出現的次數

#awk '$8!=200{arr[$1]++}END{for(i in arr){print arr[i],i}}' access.log

在這裏插入圖片描述
進一步統計出現次數排名前十的IP:

#awk '$8!=200{arr[$1]++}END{for(i in arr){print arr[i],i}}' access.log | sort -k1nr | head -n 10

在這裏插入圖片描述
另外一種實現統計前十的 方法:

#awk '$8!=200{arr[$1]++}END{PROCINFO["sorted_in"]="@val_num_desc";for(i in arr){if(cnt++==10){exit}print arr[i],i}}' access.log

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章