awk
- awk:單行指令碼
- 核心 awk:取行
- 核心 awk:取列
- 核心 awk:混合取行取列
- awk:統計功能
- 未來:判斷迴圈
- 未來:陣列
1、awk概述
四劍客 | 特點 | 擅長 |
---|---|---|
find | 查詢檔案 | 查詢檔案,與其他命令配合 |
grep/egrep | 過濾 | 過濾速度最快 |
sed | 過濾、取行、替換、刪除 | 替換修改檔案內容、取行 |
awk | 過濾、取行、取列、統計計算、判斷、迴圈... | 取行、取列、統計計算 |
- awk是一種語言,叫做單行指令碼
1、格式
取出/etc/passwd中的第1行的第1列、第3列和最後一列
awk -F: NR==1{print $1,$3,$NF} ' /etc/passwd
awk -F: '條件{動作1;動作2...}' /etc/passwd
條件:找誰
動作:幹啥
2、awk取行
1️⃣取出/etc/passwd中的第一行
NR:Number of Record 記錄號、行號。也可以寫大於幾行,小於幾行
{print $0}:輸出整行內容,$0表示當前的內容
## 簡寫
[root@Ansible-server ~]# awk 'NR==1' /etc/passwd
root:x:0:0:root:/root:/bin/bash
## 完整寫法
[root@Ansible-server ~]# awk 'NR==1{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@Ansible-server ~]# awk 'NR>=6{print $0}' /etc/passwd
2️⃣取/etc/passwd出2-5行的內容
&&:表示並且,and
||:表示或者,or
[root@Ansible-server ~]# awk 'NR>=2 && NR<=5{print $0}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
3️⃣過濾出/etc/passwd檔案中包含root或者nobody的行
[root@Ansible-server ~]# awk '/root|nobody/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
stap-server:x:155:155:Systemtap Compile Server:/opt/rh/gcc-toolset-11/root/var/lib/stap-server:/sbin/nologin
4️⃣從包含root的行開始輸出到包含nobody的行,可以使用這個功能實現擷取一個時間段的日誌
[root@Ansible-server ~]# awk '/root/ , /nobody/' /etc/passwd
-
小結
-
awk+NR:取出指定的行,指定範圍的行
-
awk+//:過濾
-
awk+其他變數:用於精確過濾(講完取列就可以使用)
[root@Ansible-server ~]# awk -F: '$3==0' /etc/passwd root:x:0:0:root:/root:/bin/bash
-
3、awk取列
1️⃣使用awk取出
ls -lh
的表示大小的列和最後一列
- NF:表示有多少列
- $NF:最後一列
[root@Ansible-server opt]# ls -lh | awk '{print $5,$9}'
[root@Ansible-server opt]# ls -lh | awk '{print $5,$NF}'
49 a.txt
4.0K mplayer
2.1K passwd
93 rh
12G rhel8.8.iso
74 sed.txt
[root@Ansible-server opt]# ls -lh | awk 'NR>1{print $5,$NF}' | column -t
49 a.txt
4.0K mplayer
2.1K passwd
93 rh
12G rhel8.8.iso
74 sed.txt
[root@Ansible-server opt]# echo 123 355 6667 87678 23 | awk '{print $(NF-1),$NF}'
87678 23
2️⃣取出/etc/passwd中第一列、第三列和第五列
-F:指定列之間的分隔符,如果不加-F則預設是空格,-F也支援正則指定分隔符
[root@Ansible-server opt]# awk -F: '{print $1,$3,$NF}' /etc/passwd | column -t
3️⃣指定複雜分隔符取出IP
⚠️在inet前有多個空格,對於awk,如果使用-F引數,每遇到一個空格就切一刀,因此為了實現把所有連續的空格作為一個整體一起切斷,我們需要在正則匹配分隔符時加上+號。
[root@Ansible-server opt]# ip address show ens160 | awk 'NR==4' | awk '{print $2}' | awk -F'/' '{print $1}'
192.168.121.141
## 進行簡化
[root@Ansible-server opt]# ip address show ens160 | awk 'NR==4' | awk -F'[ /]+' '{print $3}'
192.168.121.141
[root@Ansible-server opt]# ip address show ens160 | awk 'NR==4' | awk -F'inet |/24' '{print $2}'
192.168.121.141
- 小結
- 如果是空格、連續空格,直接使用awk取列即可
- 其他情況使用-F指定分隔符,必要時加正則實現
4、awk取行取列
awk 格式 '條件{動作}'
🌟🌟🌟🌟🌟取行+取列 取IP地址
[root@Ansible-server opt]# ip address show ens160 | awk -F'[ /]+' 'NR==4{print $3}'
192.168.121.141
🌟🌟🌟🌟🌟對列的判斷,取出/etc/passwd檔案中第三列大於1000的行,取出這些行的第一列、第三列和最後一列
[root@Ansible-server opt]# awk -F: '$3>1000{print $1,$3,$NF}' /etc/passwd | column -t
nobody 65534 /sbin/nologin
xiaoli 1001 /bin/bash
xiaowang 1002 /bin/bash
同時也支援邏輯表示式和條件表示式
如果系統swap使用超過0則輸出異常
- 條件
- 過濾出swap
- 第三列,大於0
- 動作
- 輸出“異常”
[root@Ansible-server ~]# free | awk 'NR==3 && $3>0 {print "異常"}'
# 找出能進行登陸的普通使用者
root@moudle01[13:41:27]:/opt
$ awk -F: '$3>=1000&&/bash$/{print}' /etc/passwd
xu:x:1000:1000::/home/xu:/bin/bash
xuxuxu:x:1001:1001::/home/xuxuxu:/bin/bash
過濾出/etc/passwd第四列的數字是以0或1開頭的行,輸出第一列、第三列、第四列
🍃awk中透過~可以實現對某一列進行過濾
某一列中含有xxx內容:
- ~ 表示包含的意思 $1 ~ /root/ 表示第一列中包含root
- !~表示不包含
- 之前^和$表示某一行的開頭或者結尾
- 在awk中因為awk可以取列,透過列可以過濾出一列中包含什麼...過濾出一列中以xxxx開頭或者結尾的行
[root@Ansible-server ~]# awk -F: '$4 ~ /^[01]/ {print $1,$3,$4}' /etc/passwd | column -t
5、awk統計和計算
awk進行統計有兩類案例:
1️⃣類似於
wc -l
統計次數2️⃣進行累加、求和
(1)、統計次數
統計/etc/passwd中的行數
使用awk進行行數統計
⚠️由於awk的執行過程是一行一行的讀取,END後面的內容是要在所有的行都讀取完成後在執行
[root@Ansible-server ~]# awk '{i=i+1} END{print i}' /etc/passwd
40
(2)、累加、求和
[root@Ansible-server ~]# seq 10 | awk '{sum=sum+$1}END{print sum}'
55
6、BEGIN和END
在檔案讀取開始之前執行1次:BEGIN
在檔案讀取開始之後執行1次:END
和檔案本身讀取了幾行沒有關係,
root@moudle01[11:04:43]:/script
$ awk 'BEGIN{print "你好"}' /etc/passwd
你好
root@moudle01[11:05:08]:/script
$ awk 'END{print "你好"}' /etc/passwd
你好
root@moudle01[11:06:52]:/script
$ awk 'BEGIN{print "你好"} END{print "完畢"}' /etc/passwd
你好
完畢
root@moudle01[11:30:31]:/opt
$ awk -F: 'BEGIN{print "使用者名稱\tUID\t家目錄"}{print $1,$3,$6}END{print "共有"NR"個使用者"}' user | column -t
使用者名稱 UID 家目錄
root 0 /root
bin 1 /bin
daemon 2 /sbin
adm 3 /var/adm
lp 4 /var/spool/lpd
共有5個使用者
7、awk陣列和for結合
$ awk 'BEGIN{a=10;a=20;print a}'
20
$ awk 'BEGIN{a[1]=10;a[2]=20;print a[1]}'
10
$ awk 'BEGIN{a[1]=10;a[2]=20;print a[2]}'
20
$ awk 'BEGIN{a[1]=10;a[2]="aaa";print a[2],a[1]}'
aaa 10
$ awk 'BEGIN{a["sss"]=10;a[2]="aaa";print a[2],a["sss"]}'
aaa 10
利用awk陣列處理檔案資訊,統計檔案中的資料出現了幾次
$ cat shu.txt
abc
xyz
abc
root@moudle01[17:07:33]:/opt
$ awk '{a[$1]++}END{print a["abc"]}' shu.txt
2
root@moudle01[17:07:42]:/opt
$ awk '{a[$1]++}END{print a["xyz"]}' shu.txt
1
awk中的for迴圈
for(變數名 in 陣列名){任務指令}
此時變數得到的是陣列中的下標
root@moudle01[17:17:08]:/opt
$ awk '{a[$1]++}END{for(i in a){print i,a[i]}}' shu.txt
opq 1
abc 3
xyz 2
root@moudle01[17:21:36]:/opt
$ awk '{a[$1]++}END{for(i in a){print i,"訪問次數:",a[i]}}' /var/log/httpd/access_log | sort -rn -k 3| column -t
192.168.121.1 訪問次數: 9
192.168.121.180 訪問次數: 9
192.168.121.181 訪問次數: 6
# sort的-k引數:按照第幾列排序,預設是按照空格分
# 檢視系統安全日誌,檢視有哪些IP登入錯誤
root@moudle01[17:24:09]:/opt
$ awk '/Failed password for root/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' /var/log/secure | sort -rn -k 2| column -t
192.168.121.181 1
6、awk總結
- 核心:awk取行取列
- 熟悉:awk對列比較大小
- 熟悉:awk對列進行過濾計算
- 難點:awk計算、求和