awk

1、awk

1. awk的工做原理

逐行讀取文本,默認以空格或tab鍵爲分隔符進行分割,將分割所得的各個字段保存到內建變量中,並按模式或者條件執行編輯命令。
sed命令經常使用語一整行的處理,而awk比較傾向於將一行分紅多個「字段」而後再進行處理。awk信息的讀入也是逐行讀取的,執行結果能夠經過print的功能將字段數據打印顯示。在使用awk命令的過程當中,可使用邏輯操做符「&&」表示「與」、「||」表示「或」、「!」表示「非」;還能夠進行簡單的數學運算,如+、-、*、/、%、^分別表示加、減、乘、除、取餘和乘方。html

2. 命令格式

awk 選項 '模式或條件 {操做}' 文件1 文件2 ……
awk -f 腳本文件 文件1 文件2 ……python

3. awk常見的內建變量(可直接用)

內建變量 說明
FS 列分隔符。指定每行文本的字段分隔符,默認爲空格或製表位。與「-F」做用相同
NF 當前處理的行的字段個數
NR 當前處理的行的行號(序數)
$0 當前處理的行的整行內容
$n 當前處理行的第n個字段(第n列)
FILENAME 被處理的文件名
RS 行分隔符。awk從文件上讀取資料時,將根據RS的定義把資料切割成許多條記錄,而awk一次僅讀入一條記錄,以進行處理。預設值是「\n」

2、操做實例

1. 按行輸出文本

awk '{print}' 文件名apache

輸出全部內容數組

[root@localhost ~]# cat test.txt 11 22 33 44 [root@localhost ~]# awk '{print}' test.txt 11 22 33 44 

awk '{print $0}' 文件名
輸出全部內容ruby

[root@localhost ~]# awk '{print $0}' test.txt 11 22 33 44 

awk 'NR==n,NR==m {print}' 文件名
輸出第n行至第m行的內容bash

[root@localhost ~]# awk 'NR==1,NR==3 {print $0}' test.txt 11 22 33 

awk '(NR>=n) && (NR<=m) {print}' 文件名
輸出第n行至第m行的內容app

[root@localhost ~]# awk '(NR>=1) && (NR<=3) {print}' test.txt 11 22 33 

awk 'NR==n || NR==m {print}' 文件名
輸出第n行和第m行的內容運維

[root@localhost ~]# awk 'NR==1 || NR==3 {print}' test.txt 11 33 

awk '(NR%2)==1 {print}' 文件名
輸出全部奇數行的內容dom

[root@localhost ~]# awk '(NR%2)==1 {print}' test.txt 11 33 

awk '(NR%2)==0 {print}' 文件名
輸出全部偶數行的內容ssh

[root@localhost ~]# awk '(NR%2)==1 {print}' test.txt 22 44 

awk '/^a/ {print}' 文件名
輸出以字符串a開頭的行

[root@localhost ~]# awk '/^3/ {print}' test.txt 33 

awk '/a$/ {print}' 文件名
輸出以字符串a結尾的行

[root@localhost ~]# awk '/4$/ {print}' test.txt 44 

awk 'BEGIN {x=0}; /^a/ {x++}; END {print x}' 文件名
輸出文件中以字符串a開頭行的數量

BEGIN模式表示,在處理指定的文本以前,須要先執行BEGIN模式中指定的動做;awk再處理指定的文本,以後再執行END模式中指定的動做,END{}語句塊中,每每會放入打印結果等語句。

[root@localhost ~]# awk 'BEGIN{X=0}; /^root/ {x++}; END{print x}' /etc/passwd 1 [root@localhost ~]# awk 'BEGIN{X=0}; /nologin$/ {x++}; END{print x}' /etc/passwd 39 

2. 按字段輸出文本

awk -F ":" '{print $n}' 文件名
以:號爲分隔符,輸出每行的第n個字段

[root@localhost ~]# awk -F ":" '{print $1}' /etc/passwd root bin daemon adm lp sync shutdown halt mail operator games ftp nobody systemd-network dbus polkitd abrt libstoragemgmt rpc colord saslauth setroubleshoot rtkit pulse qemu ntp radvd chrony tss usbmuxd geoclue sssd gdm rpcuser nfsnobody gnome-initial-setup avahi postfix sshd tcpdump 123456 named dhcpd apache 

awk -F ":" '{print $n,$m}' 文件名
以:號爲分隔符,輸出每行的第n個和第m個字段

[root@localhost ~]# awk -F ":" '{print $1,$3}' /etc/passwd root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 operator 11 games 12 ftp 14 nobody 99 systemd-network 192 dbus 81 polkitd 999 abrt 173 libstoragemgmt 998 rpc 32 colord 997 saslauth 996 setroubleshoot 995 rtkit 172 pulse 171 qemu 107 ntp 38 radvd 75 chrony 994 tss 59 usbmuxd 113 geoclue 993 sssd 992 gdm 42 rpcuser 29 nfsnobody 65534 gnome-initial-setup 991 avahi 70 postfix 89 sshd 74 tcpdump 72 123456 1000 named 25 dhcpd 177 apache 48 

awk -F ":" '$n<m {print $n}' 文件名
以:號爲分隔符,當第n個字段小於m時,輸出第n個字段

[root@localhost ~]# awk -F ":" '$3<5 {print $1,$3}' /etc/passwd root 0 bin 1 daemon 2 adm 3 lp 4 

awk -F ":" '!($n<m) {print}' 文件名
以:號爲分隔符,當第n個字段不小於m時,輸出整行內容

[root@localhost ~]# awk -F ":" '!($3<200) {print}' /etc/passwd polkitd:x:999:997:User for polkitd:/:/sbin/nologin libstoragemgmt:x:998:995:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin colord:x:997:994:User for colord:/var/lib/colord:/sbin/nologin saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin setroubleshoot:x:995:993::/var/lib/setroubleshoot:/sbin/nologin chrony:x:994:990::/var/lib/chrony:/sbin/nologin geoclue:x:993:988:User for geoclue:/var/lib/geoclue:/sbin/nologin sssd:x:992:987:User for sssd:/:/sbin/nologin nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin gnome-initial-setup:x:991:986::/run/gnome-initial-setup/:/sbin/nologin 123456:x:1000:1000:123456:/home/123456:/bin/bash 

awk 'BEGIN {FS=":"}; {if ($n>=m) {print}}' 文件名
以:號爲分隔符,當第n列大於等於m時,輸出整行內容

[root@localhost ~]# awk 'BEGIN {FS=":"}; {if ($3>=1000) {print}}' /etc/passwd nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin 123456:x:1000:1000:123456:/home/123456:/bin/bash 

awk -F ":" '{max=($n>=$m) ? $n : $m; {print max}}' 文件名
三元運算符。以:號爲分隔符,若是第n個字段的值大於等於第m個字段的值,則把第n個字段的值賦給max,不然把第m個字段的值賦給max

[root@localhost ~]# awk -F ":" '{max=($3>=$4) ? $3 : $4; {print max}}' /etc/passwd 0 1 2 4 7 5 6 7 12 11 100 50 99 192 81 999 173 998 32 997 996 995 172 171 107 38 75 994 59 113 993 992 42 29 65534 991 70 89 74 72 1000 25 177 48 

awk -F ":" '{print NR,$0}' 文件名
以:號爲分隔符,處理每行內容和行號,沒處理完一條記錄,NR值加1

[root@localhost ~]# awk -F ":" '{print NR,$0}' /etc/passwd 1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin 4 adm:x:3:4:adm:/var/adm:/sbin/nologin 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 6 sync:x:5:0:sync:/sbin:/bin/sync 7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 8 halt:x:7:0:halt:/sbin:/sbin/halt 9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 10 operator:x:11:0:operator:/root:/sbin/nologin 11 games:x:12:100:games:/usr/games:/sbin/nologin 12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin 13 nobody:x:99:99:Nobody:/:/sbin/nologin 14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin 15 dbus:x:81:81:System message bus:/:/sbin/nologin 16 polkitd:x:999:997:User for polkitd:/:/sbin/nologin 17 abrt:x:173:173::/etc/abrt:/sbin/nologin 18 libstoragemgmt:x:998:995:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin 19 rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin 20 colord:x:997:994:User for colord:/var/lib/colord:/sbin/nologin 21 saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin 22 setroubleshoot:x:995:993::/var/lib/setroubleshoot:/sbin/nologin 23 rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin 24 pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin 25 qemu:x:107:107:qemu user:/:/sbin/nologin 26 ntp:x:38:38::/etc/ntp:/sbin/nologin 27 radvd:x:75:75:radvd user:/:/sbin/nologin 28 chrony:x:994:990::/var/lib/chrony:/sbin/nologin 29 tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin 30 usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin 31 geoclue:x:993:988:User for geoclue:/var/lib/geoclue:/sbin/nologin 32 sssd:x:992:987:User for sssd:/:/sbin/nologin 33 gdm:x:42:42::/var/lib/gdm:/sbin/nologin 34 rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin 35 nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin 36 gnome-initial-setup:x:991:986::/run/gnome-initial-setup/:/sbin/nologin 37 avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin 38 postfix:x:89:89::/var/spool/postfix:/sbin/nologin 39 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin 40 tcpdump:x:72:72::/:/sbin/nologin 41 123456:x:1000:1000:123456:/home/123456:/bin/bash 42 named:x:25:25:Named:/var/named:/sbin/nologin 43 dhcpd:x:177:177:DHCP server:/:/sbin/nologin 44 apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin 

awk -F ":" '$n~ "a" {print $m}' 文件名
以:號爲分隔符,輸出第n個字段中含有字符串a的行的第m個字段

[root@localhost ~]# awk -F ":" '$7~ "/bash" {print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash 123456:x:1000:1000:123456:/home/123456:/bin/bash 

awk -F ":" '($n~ "a") && (NF==m) {print}' 文件名
以:號爲分隔符,輸出第n個字段中含有字符串a且有m個字段的行

[root@localhost ~]# awk -F ":" '($1~ "root") && (NF==7) {print $1,$2}' /etc/passwd root x 

awk -F 「:」 '($n != "a") && ($m != "b") {print}' 文件名
以:號爲分隔符,輸出第n個字段既不是字符串a也不是字符串b的行

[root@localhost ~]# awk -F ":" '($7!="/bin/bash")&&($7!="/sbin/nologin") {print}' /etc/passwd sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt 

經過管道、雙引號調用Shell命令

echo $PATH | awk 'BEGIN{RS=":"}; END{print NR}'
以:號爲分隔符,輸出總字段數

[root@localhost ~]# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin [root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}; END{print NR}' 5 

awk -F: '/a$/ {print | "wc -l"}' 文件名
以:號爲分隔符,統計以字符串a爲結尾的行的行數,同等於「grep -c」命令

[root@localhost ~]# awk -F: '/bash$/ {print | "wc -l"}' /etc/passwd 2 [root@localhost ~]# grep -c "/bash"$ /etc/passwd 2 

free -m | awk '/Mem:/ {print int($3/($3+$4)*100)"%"}'
查看當前內存使用百分比

[root@localhost ~]# free -m total used free shared buff/cache available Mem: 1984 326 1257 9 400 1439 Swap: 4095 0 4095 [root@localhost ~]# free -m | awk '/Mem:/ {print int($3/($3+$4)*100)"%"}' 20% 

top -b -n 1 | grep Cpu | awk -F "," '{print $4}' | awk '{print $1}'
查看當前CPU空閒率,"-b -n 1"表示只須要1次的輸出結果

[root@localhost ~]# top -b -n 1 | grep Cpu | awk -F "," '{print $4}' | awk '{print $1}' 97.0 

date -d "$(awk -F "." '{print $1}' /proc/uptime) second ago" +"%F %H:%M:%S"
顯示上次系統重啓時間,等同於uptime;「second ago」爲顯示多少秒前的時間,+"%F %H:%M:%S"爲時間格式,%F等同於%Y-%m-%d。

[root@localhost ~]# date -d "$(awk -F "." '{print $1}' /proc/uptime) second ago" +"%F %H:%M:%S" 2021-07-29 11:07:15 

awk 'BEGIN {N=0; while ("w" | getline) n++; {print n=2}}'
調用w命令,並用來統計在線用戶數

[root@localhost ~]# awk 'BEGIN {N=0; while ("w" | getline) n++; {print n=2}}' 2 

awk 'BEGIN {"hostname" | getline; {print}}'
調用hostname,並輸出當前的主機名

[root@localhost ~]# awk 'BEGIN {"hostname" | getline; {print}}' localhost.localdomain 

注:當getline左右無重定向符「<」或「|」時,awk首先讀取到了第一行,就是1,而後getline,就獲得了1下面的第二行,就是2,由於getline以後,awk會改變對應的NF,FNR和$0等內部變量,因此此時的$0的值就再也不是1,而是2了,而後將它打印出來。
當getline左右有重定向符「<」或「|」時,getline則做用於定向輸入文件,因爲該文件是剛打開,並無被awk讀入一行,只是getline讀入,那麼getline返回的是該文件的第一行,而不是隔行。
FNR:awk當前讀取的記錄數,其變量值小於等於NR(好比當讀取第二個文件時,FNR是從0開始從新計數,而NR不會),所以可以使用「NR==FNR」來判斷是否在讀取第一個文件。

[root@localhost ~]# seq 10 | awk '{getline; print}' 2 4 6 8 10 [root@localhost ~]# seq 10 | awk '{print; getline}' 1 3 5 7 9 

CPU使用率

[root@localhost ~]# cat cpu.sh #!/bin/bash cpu_us=`top -b -n 1 | grep Cpu | awk '{print $2}'` echo $cpu_us cpu_sy=`top -b -n 1 | grep Cpu | awk -F ',' '{print $2}' | awk '{print $1}'` echo $cpu_sy echo "$cpu_us+$cpu_sy" | bc [root@localhost ~]# ./cpu.sh 0.0 3.1 3.1 

echo "A B C D" | awk '{OFS="|"; print $0 ;$1=$1; print $0}'

$1=$1是用來從新激活$0的從新賦值,也就是說每個字段和字段數NF的改變會促使awk從新計算$0的值,一般是在改變OFS後面須要輸出$0時這樣作。

[root@localhost ~]# echo "A B C D" | awk '{OFS="|"; print $0 ;$1=$1; print $0}' A B C D A|B|C|D 

3. awk數組循環

1.使用awk創建數組

awk 'BEGIN {a[0]=10; a[1]=20; print a[0]}'                    

awk 'BEGIN {a[0]=10; a[1]=20; print a[1]}'

[root@localhost ~]# awk 'BEGIN {a[0]=10; a[1]=20; print a[0]}' 10 [root@localhost ~]# awk 'BEGIN {a[0]=10; a[1]=20; print a[1]}' 20 

awk 'BEGIN {a["abc"]=10; a["xyz"]=20; print a["abc"]}'
awk 'BEGIN {a["abc"]=10; a["xyz"]=20; print a["xyz"]}'

[root@localhost ~]# awk 'BEGIN {a["abc"]=10; a["xyz"]=20; print a["abc"]}' 10 [root@localhost ~]# awk 'BEGIN {a["abc"]=10; a["xyz"]=20; print a["xyz"]}' 20 

awk 'BEGIN {a["abc"]="aabbcc"; a["xyz"]="xxyyzz"; print a["abc"]}'
awk 'BEGIN {a["abc"]="aabbcc"; a["xyz"]="xxyyzz"; print a["xyz"]}'

[root@localhost ~]# awk 'BEGIN {a["abc"]="aabbcc"; a["xyz"]="xxyyzz"; print a["abc"]}' aabbcc [root@localhost ~]# awk 'BEGIN {a["abc"]="aabbcc"; a["xyz"]="xxyyzz"; print a["xyz"]}' xxyyzz 

awk 'BEGIN {a[0]=10; a[1]=20; a[2]=30; for (i in a) {print i,a[i]}}'

[root@localhost html]# awk 'BEGIN {a[0]=10; a[1]=20; a[2]=30; for (i in a) {print i,a[i]}}' 0 10 1 20 2 30 

注1:BEGIN中的命令只執行一次
注2:awk數組的下標除了可使用數字,也可使用字符串,字符串須要使用雙引號

  1. awk循環遍歷
[root@localhost ~]# cat test1.txt aaa aaa bbb ccc aaa bbb aaa [root@localhost ~]# awk '{a[1]++} END{for(i in a) {print a[i]}}' test1.txt 7 

注:a[1]初始爲0,a[1]++後即爲1,而這裏awk中的a[1]++最終的值是由test1.txt文本內容有多少行決定的,文本逐行讀取完畢後再執行END中的命令。

使用awk獲取文件test1.txt中的重複行及次數

[root@localhost ~]# awk '{a[$1]++} END{for(i in a) {print a[i],i}}' test1.txt 4 aaa 1 ccc 2 bbb [root@localhost ~]# awk '{a[$1]++} END{for(i in a) {print a[i],i}}' test1.txt | sort -r 4 aaa 2 bbb 1 ccc 

注:也可以使用sort排序後經過「uniq -c」獲取重複行次次數。以上操做是咱們在平常工做中經常使用的運維手段,crontab平常監控以及排障時常常用獲得。
擴展--運維工做經常使用的查看命令或文件

監控項目 監控命令或文件
cpu負載 uptime
內存容量 free -m
硬盤空間 df -h
網卡流量 ifconfig 網卡名稱(如ens33)
安裝的軟件包數量 rpm -qa | wc -l
帳戶數量 /etc/passwd
當前登陸的帳戶數量 who
進程數量 ps aux
異常登陸信息 /var/log/secure

例如:
使用awk統計httpd訪問日誌中每一個客戶端IP的出現次數
awk '{ip[$1]++} END{for (i in ip) {print ip[i],i}}' /var/log/httpd/access_log | sort -r

[root@localhost ~]# awk '{ip[$1]++} END{for (i in ip) {print ip[i],i}}' /var/log/httpd/access_log | sort -r 82 192.168.122.88 

注:定義數組,數組名稱爲ip,數字的下標爲日誌文件的第1列(也就是客戶端的IP地址),++的目的在於對客戶端進行統計技術,客戶端IP出現一次計數器就加1.END中的指令在讀取完文件後執行,經過循環將全部統計信息輸出,for循環遍歷的是數組名ip的下標。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息