1. 程式人生 > 其它 >15Linux三劍客之awk命令

15Linux三劍客之awk命令

目錄

awk命令

AWK 是一種處理文字檔案的語言

awk 主要用來處理檔案,將文字按照指定的格式輸出。其中包含變數,迴圈以及陣列

awk [選項] '匹配規則和處理規則' [處理文字路徑]

選項

-F			指定輸入檔案折分隔符

匹配規則

字串


正則表示式

匹配規則主要是正則表示式

處理規則

設定變數
設定陣列
陣列迴圈
加減乘數運算
字串拼接
BEGIN{}		: BEGIN是在awk處理文字之前執行
//			: 使用的匹配規則
{}			:迴圈(每次只處理一行資料)
END{}		:當所有的處理全部執行完畢之後,執行END中的相關操作

案例

案例1:把/etc/passwd中的包含root的行打印出來

[root@localhost ~]#awk  '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

案例2:把/etc/passwd中以root開頭的行打印出來

[root@localhost ~]#awk '/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash

案例3:將/etc/passwd中匹配第三列和第五列的資料

awk -F: '{print $3,$5}' /etc/passwd

案例4:列印以root或者mysql開頭的行的解析器

[root@localhost ~]#awk '/^(root|mysql)/' /etc/passwdroot:x:0:0:root:/root:/bin/bashmysql:x:997:995::/home/mysql:/sbin/nologin

awk的工作原理

(1)awk會接收一行作為輸入,並將這一行賦給awk的內部變數$0,每一行也可稱為一個記錄,行的邊界是以換行符作為結束(表明:awk是一行一行的去處理文字的)(2)然後,剛剛讀入的行被以:為分隔符分解成若干欄位(或域),每個欄位儲存在已編號的變數中,編號從$1開始,最多達100個欄位注意:如果未指定行分隔符,awk將使用內建變數FS的值作為預設的行分隔符,FS預設值為空格,如果說要指定分隔符,需要使用-F引數或者重新定義FS變數(3)使用print函式列印,如果$1$3之間沒有逗號,它倆在輸出時將貼在一起,應該在$1,$3之間加逗號,該逗號與awk的內建變數OFS保持一致,OFS預設為空格,於是以空格為分隔符輸出$1和$3我們可以指定:awk -F: 'BEGIN{OFS="-"}{print $1,$3}' /etc/passwd(4)輸出之後,將從檔案中獲取另一行,然後覆蓋給$0,繼續(2)的步驟將該行內容分隔成欄位。。。繼續(3)的步驟該過程一直持續到所有行處理完畢

awk中的變數

$0: 儲存當前行的內容NR: 記錄號(行號),每處理完一條記錄,NR值加1NF: 儲存記錄的欄位數,$1,$2...$100FS: 輸入欄位分隔符,預設空格OFS:輸出欄位分隔符

注: -F引數的優先順序小於FS變數的優先順序

​ 所有的變數的定義都應該放在BEGIN裡面

案例

案例1:要求輸出第7行之後的內容且第12行之前的內容輸出出來,包含行號

[root@localhost ~]#awk 'NR>7&&NR<12 {print NR,$0}' /etc/passwd8 halt:x:7:0:halt:/sbin:/sbin/halt9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin10 operator:x:11:0:operator:/root:/sbin/nologin11 games:x:12:100:games:/usr/games:/sbin/nologin

案例2: 要求輸出倒數第3列

awk -F: '{print $(NF-2)}' /etc/passwd

案例3:要求以:分割,並輸出第3列和第5列,第三列和第五列之間使用+號分割

awk -F: 'BEGIN{OFS="+"}{print $3,$5}' /etc/passwd

格式化輸出

printf函式

%s 字元型別%d 數值型別佔15格的字串- 表示左對齊,預設是右對齊printf預設不會在行尾自動換行,加\n

案例

案例1:要求輸出第1列和最後一列,排版整齊

[root@localhost ~]#awk -F: '{printf "%-16s %s \n", $1,$NF}' /etc/passwd

操作模式

1、正則模式awk -F: '/^xxx/' /etc/passwd2、比較模式> < awk -F 'NR > 7' /etc/passwd3、條件模式awk -F 'NR > 7' /etc/passwd4、算數運算awk -F '{print $3,$3+1}' /etc/passwd 5、範圍模式awk -F: '/root/,/ftp/{print $1}' /etc/passwd

流程控制

if判斷

單分支if () {}雙分支if () {} else {}多分支if(){} else if() {} else{}注:單分支情況下是可以省略if,多分支情況下不能省略
案例

案例1:列印奇數行的資料

awk -F: '{if(NR%2==1){print NR,$0}}' /etc/passwd
awk -F: '{if(NR%2){print NR,$0}}' /etc/passwd
awk -F: 'NR%2==1{print NR,$0}' /etc/passwd

案例2:要求在奇數行前輸出奇數,偶數行前輸出偶數

awk -F: '{if(NR%2){printf "奇數行:%s\n",$0}else{printf "偶數行:%s\n",$0}}' /etc/passwd

for迴圈

for (變數 in 陣列) {語句}for (變數;條件;表示式){語句}

案例

案例1:統計 /etc/nginx/nginx.conf中的所有的詞的個數

egrep -o "[a-zA-Z0-9]+" /etc/nginx/nginx.conf|awk '{l1[$1]=l1[$1]+1}END{for(i in l1){printf "%-10s %s \n", i,l1[i] }}'
egrep -o "[a-zA-Z0-9]+" /etc/nginx/nginx.conf|awk '{l1[$1]++}END{for(i in l1){printf "%-10s %s \n", i,l1[i] }}'

案例2:輸入一個檔案路徑,要求打印出它的數字許可權(不允許使用stat)

[root@localhost ~]# ll  | awk 'BEGIN{FS=""}{if($2=="r"){u=u+4} if($3=="w"){u=u+2} if($4=="x"){u=u+1} if($5=="r"){g=g+4} if($6=="w"){g=g+2} if($7=="x"){g=g+1} if($8=="r"){o=o+4} if($9=="w"){o=o+2} if($10=="x"){o=o+1}}END{print u,g,o}'