-
awk並不是一個簡單命令,它實際上是一門編程語言,適合處理文本類數據,awk處理文本是以記錄(文本中的行)爲單位的,它會遍歷文件的每條記錄並進行處理linux
-
awk語法格式: awk 'Pattern {Action}' filenamenginx
-
awk工做原理:awk讀取一條記錄,並將記錄賦值給內部變量$0,記錄被分隔符分割成多個字段,每一個字段存儲到指定編號的變量中,從$1開始,(awk內部變量FS用來指定字段分隔符,默認爲空格,包含製表符和空格符,也可用-F來自定義分隔符),對於每一條記錄,按照給定的Pattern進行匹配,匹配成功則執行Action,匹配失敗,則不執行Action,其中Pattern和Action都是可選的,但必須提供其中一個,若是未指定Pattern,則對全部輸入行都執行Action,若是未指定Action,則輸出匹配行的內容git
-
$0 表示文本中的一條記錄即一行內容redis
[root@linux01 ~]# head -n5 /etc/passwd| awk '{print $0}' root:x:0:0:root:/root:/bin/bash 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
- 截取其中若干列內容,awk默認空格爲分隔符,若是要改變分隔符可用"-F"選項自定義
[root@linux01 ~]# head -n5 /etc/passwd| awk -F: '{print $1,$3}' root 0 bin 1 daemon 2 adm 3 lp 4
- 添加修飾內容,BEGIN和END是awk關鍵字,前者表示在awk對文件處理前首先被執行,後者表示在awk對文件處理後被執行
[root@linux01 ~]# head -n5 /etc/passwd| awk -F: 'BEGIN {print "=====begin====="} {print $1,$3} END {print "=====end====="}' =====begin===== root 0 bin 1 daemon 2 adm 3 lp 4 =====end=====
- awk可實現數學計算,$3+$4表示以:(冒號)分隔的第三和第四列之和
[root@linux01 ~]# head -n5 /etc/passwd| awk -F: 'BEGIN {print "=====begin====="} {print $1,$2,$3+$4} END {print "=====end====="}' =====begin===== root x 0 bin x 2 daemon x 4 adm x 7 lp x 11 =====end=====
- 針對輸出結果進行過濾,~表示匹配意思
[root@linux01 ~]# head -n5 /etc/passwd| awk -F: 'BEGIN {print "=====begin====="} $1~/lp/ {print $1,$2,$3+$4} END {print "=====end====="}' =====begin===== lp x 11 =====end=====
- 巧妙顯示奇/偶行,'NR%2==0 {next}'做爲awk的Pattern匹配部分,其中NR表示當前記錄的行號,整句表示NR被整除爲TRUE的話,則執行next動做,而遇到next,就會忽略後面的Action部分,直接進入下一行處理,因此顯示爲奇數行輸出
[root@linux01 ~]# cat -n file1.txt 1 test 1 2 one two three proce 3 test 2 4 test test file [root@linux01 ~]# awk 'NR%2==0 {next} {print NR,$0}' file1.txt 1 test 1 3 test 2 [root@linux01 ~]# awk 'NR%2!=0 {next} {print NR,$0}' file1.txt 2 one two three proce 4 test test file
- 固定行合併,經過第一部分和第二部分語句,能夠實現3行一組的前兩行內容存放到變量T中,當處理第三行時,就會把全部以前存儲的內容都輸出來,而後清空變量T,再進行下一組數據處理
[root@linux01 ~]# cat -n file1.txt 1 test 1 2 one two three proce 3 test 2 4 test test file 5 wsr239wfgrte 6 fw9efs0art4 7 4tesd8w40-sdgd 8 43q8wsfjwrskdpoht 9 rear8ut9spgoog 10 45678 11 s34otjvsa; 12 4su02q9jdgopro[ [root@linux01 ~]# awk 'NR%3!=0 {T=(T" "$0);next} {print T,$0;T=""}' file1.txt test 1 one two three proce test 2 test test file wsr239wfgrte fw9efs0art4 4tesd8w40-sdgd 43q8wsfjwrskdpoht rear8ut9spgoog 45678 s34otjvsa; 4su02q9jdgopro[
- 以上案例存在一個小問題,文件行數恰好是3的倍數,若是不是3的倍數呢...
[root@linux01 ~]# cat -n file1.txt 1 test 1 2 one two three proce 3 test 2 4 test test file 5 wsr239wfgrte 6 fw9efs0art4 7 4tesd8w40-sdgd 8 43q8wsfjwrskdpoht 9 rear8ut9spgoog 10 45678 11 s34otjvsa; [root@linux01 ~]# awk 'NR%3!=0 {T=(T" "$0);next} {print T,$0;T=""}' file1.txt -->發現丟失了10,11行內容 test 1 one two three proce test 2 test test file wsr239wfgrte fw9efs0art4 4tesd8w40-sdgd 43q8wsfjwrskdpoht rear8ut9spgoog [root@linux01 ~]# awk 'NR%3!=0 {T=(T" "$0);next} {print T,$0;T=""} END {print T}' file1.txt -->改進後命令,由於文本行數不是3的倍數時,不是3的倍數的最後一組記錄存放在變量T中,只要咱們把它輸出便可完美解決此問題 test 1 one two three proce test 2 test test file wsr239wfgrte fw9efs0art4 4tesd8w40-sdgd 43q8wsfjwrskdpoht rear8ut9spgoog 45678 s34otjvsa;
- 不定行數合併,在於用正則來找規律分組
[root@linux01 ~]# cat -n file1.txt 1 test 1 2 one two three proce 3 test 2 4 abc bca file 5 wsr239wfgrte 6 fw9efs0art4 7 4tesd8w40-sdgd 8 test 3 9 43q8wsfjwrskdpoht 10 rear8ut9spgoog 11 45678 12 s34otjvsa; 13 test 4 [root@linux01 ~]# awk 'BEGIN {T=""} /test/ {print T;T=$0;next} {T=T" "$0} END {print T}' file1.txt test 1 one two three proce test 2 abc bca file wsr239wfgrte fw9efs0art4 4tesd8w40-sdgd test 3 43q8wsfjwrskdpoht rear8ut9spgoog 45678 s34otjvsa; test 4
- 合併全部行
[root@linux01 ~]# cat -n file1.txt 1 test 1 2 one two three proce 3 test 2 4 abc bca file 5 wsr239wfgrte 6 fw9efs0art4 7 4tesd8w40-sdgd 8 test 3 9 43q8wsfjwrskdpoht 10 rear8ut9spgoog 11 45678 12 s34otjvsa; 13 test 4 [root@linux01 ~]# awk '{T=T" "$0} END {print T}' file1.txt test 1 one two three proce test 2 abc bca file wsr239wfgrte fw9efs0art4 4tesd8w40-sdgd test 3 43q8wsfjwrskdpoht rear8ut9spgoog 45678 s34otjvsa; test 4
** 輸出多個文件內容sql
[root@linux01 ~]# cat new.txt root:x:0:0:root:/root:/bin/bash this is a file good ha feng file [root@linux01 ~]# cat test.txt /0/,/3/p sfwefov w342re0k fewfklfs;ar sfd9wo4sd [root@linux01 ~]# awk '{print $0}' new.txt test.txt root:x:0:0:root:/root:/bin/bash this is a file good ha feng file /0/,/3/p sfwefov w342re0k fewfklfs;ar sfd9wo4sd
** 輸出第一個文件的第一行和第二個文件的第二行內容,NR表示已讀記錄數,不論有幾個文件,每讀一條記錄,值就會加1,FNR表示當前文件已讀記錄數,每讀取一條記錄,值就會加1,但更換文件後,該變量會從新從零開始,NR==FNR時,表示awk正在處理第一個文件,NR>FNR時,表示正在處理第二個文件,FILENAME表示當前處理文件的文件名shell
[root@linux01 ~]# cat new.txt root:x:0:0:root:/root:/bin/bash this is a file good ha feng file [root@linux01 ~]# cat test.txt /0/,/3/p sfwefov w342re0k fewfklfs;ar sfd9wo4sd [root@linux01 ~]# awk 'NR==FNR&&FNR==1 {print FILENAME,$0} NR>FNR&&FNR==2 {print FILENAME,$0}' n ew.txt test.txt new.txt root:x:0:0:root:/root:/bin/bash test.txt sfwefov
** 上面的案例在處理兩個以上文件時有所侷限,咱們能夠轉變一下思路,引入一個環境變量,叫作ARGIND,用來指示當前處理的文件編號編程
[root@linux01 ~]# cat new.txt root:x:0:0:root:/root:/bin/bash this is a file good ha feng file [root@linux01 ~]# cat test.txt /0/,/3/p sfwefov w342re0k fewfklfs;ar sfd9wo4sd [root@linux01 ~]# cat file1.txt test 1 one two three proce test 2 abc bca file wsr239wfgrte fw9efs0art4 4tesd8w40-sdgd test 3 43q8wsfjwrskdpoht rear8ut9spgoog 45678 s34otjvsa; test 4 [root@linux01 ~]# awk 'ARGIND==1&&FNR==1 {print FILENAME,$0} ARGIND==2&&FNR==2 {print FILENAME,$0} ARGIND==3&&FNR==3 {print FILENAME,$0}' new.txt test.txt file1.txt new.txt root:x:0:0:root:/root:/bin/bash test.txt sfwefov file1.txt test 2
** 上面案例還能夠用相似數組方式處理,ARGV表示命令行參數的數組vim
[root@linux01 ~]# cat new.txt root:x:0:0:root:/root:/bin/bash this is a file good ha feng file [root@linux01 ~]# cat test.txt /0/,/3/p sfwefov w342re0k fewfklfs;ar sfd9wo4sd [root@linux01 ~]# cat file1.txt test 1 one two three proce test 2 abc bca file wsr239wfgrte fw9efs0art4 4tesd8w40-sdgd test 3 43q8wsfjwrskdpoht rear8ut9spgoog 45678 s34otjvsa; test 4 [root@linux01 ~]# awk 'FILENAME==ARGV[1]&&FNR==1 {print FILENAME,$0} FILENAME==ARGV[2]&&FNR==2 {print FILENAME,$0} FILENAME==ARGV[3]&&FNR==3 {print FILENAME,$0}' new.txt test.txt file1.txt new.txt root:x:0:0:root:/root:/bin/bash test.txt sfwefov file1.txt test 2
** 咱們想用/etc/shadow文件中的加密字段替換/etc/passwd文件中的x密碼字段,OFS表示輸出時指定的分隔符,FS表示字段分隔符,讀取shadow文件時,把加密字段內容放入下標爲用戶列的數組中,再讀取passwd文件時,再賦值給x密碼字段,輸出修改後內容便可數組
[root@linux01 ~]# awk 'BEGIN {OFS=FS=":"} NR==FNR {a[$1]=$2} NR>FNR {$2=a[$1];print}' /etc/shadow /etc/passwd root:$6$CYXcNKe6hd7jzBgx$cA8WUgq/mYEymotuD0YAJRBkYtgc5nc8MFfPokHjC0LrfmHGtSIx3zE0YS5ML2Dc2YaG8Kl7khssL0faik7AS.:0:0:root:/root:/bin/bash bin:*:1:1:bin:/bin:/sbin/nologin daemon:*:2:2:daemon:/sbin:/sbin/nologin adm:*:3:4:adm:/var/adm:/sbin/nologin lp:*:4:7:lp:/var/spool/lpd:/sbin/nologin sync:*:5:0:sync:/sbin:/bin/sync shutdown:*:6:0:shutdown:/sbin:/sbin/shutdown halt:*:7:0:halt:/sbin:/sbin/halt mail:*:8:12:mail:/var/spool/mail:/sbin/nologin operator:*:11:0:operator:/root:/sbin/nologin games:*:12:100:games:/usr/games:/sbin/nologin ftp:*:14:50:FTP User:/var/ftp:/sbin/nologin nobody:*:99:99:Nobody:/:/sbin/nologin systemd-bus-proxy:!!:999:997:systemd Bus Proxy:/:/sbin/nologin systemd-network:!!:192:192:systemd Network Management:/:/sbin/nologin dbus:!!:81:81:System message bus:/:/sbin/nologin polkitd:!!:998:996:User for polkitd:/:/sbin/nologin tss:!!:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin postfix:!!:89:89::/var/spool/postfix:/sbin/nologin sshd:!!:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin chrony:!!:997:995::/var/lib/chrony:/sbin/nologin jenkins:!!:996:994:Jenkins Automation Server:/var/lib/jenkins:/bin/false gitlab-www:!!:995:992::/var/opt/gitlab/nginx:/bin/false git:!!:994:991::/var/opt/gitlab:/bin/sh gitlab-redis:!!:993:990::/var/opt/gitlab/redis:/bin/false gitlab-psql:!!:992:989::/var/opt/gitlab/postgresql:/bin/sh gitlab-prometheus:!!:991:988::/var/opt/gitlab/prometheus:/bin/sh virftp:!!:1000:1000::/home/virftp:/sbin/nologin
** getline操做文件案例,你會以爲getline命令也能夠實現奇偶行輸出功能,但不建議這樣用,由於有缺憾,只有在處理文本總數是偶數行時適用,在awk中,當getline左右沒有"<" "|"時,getline是對當前打開文件操做,表示讀取當前行的下一行內容,並把數據賦值給$0,同時更新NF,NR,FNRbash
[root@linux01 ~]# seq 10|awk '{getline;print}' 2 4 6 8 10 [root@linux01 ~]# seq 10|awk '{print;getline}' 1 3 5 7 9 [root@linux01 ~]# seq 10|awk '{print;getline;print}' 1 2 3 4 5 6 7 8 9 10 [root@linux01 ~]# seq 11|awk '{getline;print}' -->若是換成奇數行內容getline命令就會出錯了 2 4 6 8 10 11
** 在awk中,當getline左右有重定向符"< 、<<"或"|"時,getline做用於其後的輸入文件而不是當前打開的文件,因爲輸入文件是新打開的,並無被awk讀取,所以getline返回的是該文件的第一行,而不是當前讀取文件的隔行內容,getline的返回值: 1:表示正常讀取一行數據;0:表示到了文件末尾;-1:表示讀取遇到錯誤;所以案例中當處理test文件第一行內容時,getline會讀取文件num的內容,直至文件指針指向文件末尾,之後每處理一行文件test的數據,getline返回值都是0,因此不會再有文件num的內容輸出,getline重定向文件時,後面必須跟字符串類型,所以文件名必定要加雙引號
[root@linux01 ~]# cat test.txt 1 /sdfa/,/ewra/p 2 sfwefov 3 wsfresdfwek 4 fewfklfs;ar 5 sfdsfawowesd [root@linux01 ~]# cat num.txt 10 20 30 40 50 60 [root@linux01 ~]# awk '' test.txt [root@linux01 ~]# awk '{print $0;while((getline < "num.txt") > 0) print $0}' test.txt 1 /sdfa/,/ewra/p 10 20 30 40 50 60 2 sfwefov 3 wsfresdfwek 4 fewfklfs;ar 5 sfdsfawowesd
** 用system調用shell,awk經過system()函數來調用shell的程序
[root@linux01 ~]# awk 'BEGIN {system("ls -al")}' 總用量 136 dr-xr-x---. 8 root root 4096 12月 11 15:13 . dr-xr-xr-x. 18 root root 256 11月 23 21:53 .. -rw-r----- 1 root root 1502 11月 24 21:29 1.log -rw-r--r-- 1 root root 161 11月 20 10:38 adduser.sh -rw-------. 1 root root 1422 11月 14 18:11 anaconda-ks.cfg -rw-------. 1 root root 18728 12月 11 11:56 .bash_history -rw-r--r--. 1 root root 18 12月 29 2013 .bash_logout -rw-r--r--. 1 root root 176 12月 29 2013 .bash_profile -rw-r--r--. 1 root root 176 12月 29 2013 .bashrc drwxr-xr-x 3 root root 18 11月 28 23:08 .config -rw-r--r--. 1 root root 100 12月 29 2013 .cshrc -rw-r--r-- 1 root root 91 11月 20 10:33 deluser.sh -rw-r--r-- 1 root root 151 12月 10 12:12 file1.txt -rw-r--r-- 1 root root 56 11月 24 01:08 .gitconfig -rw-r--r-- 1 root root 4360 11月 22 15:11 :ii:wq -rw-r--r-- 1 root root 20 12月 11 10:59 k1.txt -rw------- 1 root root 54 11月 23 01:29 .lesshst drwxr-xr-x 3 root root 19 11月 28 23:08 .local drwxr-x--- 2 root root 19 11月 24 21:28 logs -rw-r--r-- 1 root root 66 12月 10 21:33 new.txt -rw-r--r-- 1 root root 18 12月 11 15:13 num.txt -rw-r--r-- 1 root root 1494 11月 23 17:38 passwd -rw-r--r-- 1 root root 12288 11月 27 14:54 .passwd.swp drwxr----- 3 root root 19 11月 20 20:47 .pki -rw------- 1 root root 1024 11月 29 00:45 .rnd drwxr-xr-x 3 root root 32 11月 23 21:38 sample drwx------ 2 root root 82 11月 23 16:34 .ssh -rw-r--r--. 1 root root 129 12月 29 2013 .tcshrc -rw-r--r-- 1 root root 43 11月 22 11:27 tee -rw-r--r-- 1 root root 70 12月 11 11:40 test.txt -rw------- 1 root root 5627 12月 10 12:12 .viminfo -rw------- 1 root root 4286 11月 27 18:01 .viminfo.tmp