一、簡介
awk命令是一種編程語言,用于在linux/unix下對文本和數據進行掃描和處理的工具,其數據來源可以為標準輸入、文件、管道等等。awk命令會從第一行輸入開始逐行掃描至最后一行,尋找其中匹配特定模式的行,并在相應的行上執行用戶指定的操作。Awk命令的基本架構由模式匹配和處理動作組成,默認處理動作為print打印行。
二、awk命令的使用
1、命令格式
gawk [options] 'program...' FILE ...
2、常見選項
-F fs:指明字段分隔符;
-v var=value:自定義變量;
-f programfile:從文件中讀取program命令;
3、program語句
其program語句的常見格式為:PATTERN{action,statements}
,其中多個program語句之間通過;
分隔。
- 其中PATTERN格式為:
1)empty:空模式,表示匹配每一行,如:awk -F: '{print $1,$3}' /etc/passwd 表示以:
為分隔符,打印每行的第一和第三個字段 。
2)/regular expression/:僅處理能夠被此模式匹配到的行,如:awk -F: '/^root/{print $1,$3}' /etc/passwd,表示以:
為分隔符,打印以root開頭的行的第一和第三個字段;
3)/PATTERN1/,/PATTERN2/:表示僅處理從第一個被pattern1匹配到行,到第一個被pattern2所匹配的行之間的所有行,如:awk -F: '/root/,/shutdown/{print $1,$3}' /etc/passwd,表示以:
為分隔符,打印從第一個以root開頭的行到第一個以shutdown開頭的行之間的所有行的第一和第三個字段。
4)relation expression:使用關系表達式進行匹配,只有結果會真的行才會被處理,如:awk -F: '(NR>=10&&NR<=20){print $1,$3}' /etc/passwd,表示以:
為分隔符,打印10-20行的第一和第三個字段;
5)BEGIN{}和END{}:
BEGIN{}:表示在開始處理行前執行一次指定的操作;
END{}:表示在結束對行的處理后執行一次指定的操作;
如:awk -F: 'BEGIN{print "This is the begin."};{print $1,$3};END{print "This is the end."}' /etc/passwd,表示在執行行打印操作前,先打印指定的字符串"This is the begin.",在執行行打印操作后再打印字符串“This is the end.”
- program語句的變量
program中內置了一些變量,在編寫program語句時能夠直接調用相應的變量,進而簡化語句。調用內建變量時無需加$
。
FS:輸入字段分隔符,默認為空白字符;
OFS:輸出字段分隔符,默認為空白字符;
RS:輸入時的換行符;
ORS:輸出時的換行符;
NF:每行的字段數,$NF表示最后一個字段;
NR:表示行數;
FNR:若提供多個文件,則分別計算各文件的行數;
FILENAME:當前文件名;
ARGC:命令行參數的個數;
ARGV:參數數組,保存的是命令行給定的各參數;
另外也可以在awk命令中自定義相關的變量,可以使用-v選項自定義變量,也可以在語句當中進行賦值操作,如:awk 'BEGIN{test="hello awk"; print test}'、ls -l | awk '/root/{hello="this is a test.";print $3,hello}'
- action
常見的action動作有:print、printf
1)print命令
其使用格式類似于print item1,item2,...
,使用逗號作為分隔符,輸出的item可以為字符串,也可以為數值,也可以為當前記錄的字段、變量或表達式等。如果省略了item,則相當于print $0打印所有行。
2)printf命令
printf命令常用于格式化輸出awk命令的執行結果信息。其格式類似于printf FORMAT,item1,item2...
,其中必須指定FORMAT格式;如需換行,需手動添加\n換行符;在FORMAT中需要分別為后面的每個item指定一個格式符。
其對應的格式符有:
%c: 顯示字符的ASCII碼;
%d, %i: 顯示十進制整數;
%e, %E: 科學計數法數值顯示;
%f:顯示為浮點數;
%g, %G:以科學計數法或浮點形式顯示數值;
%s:顯示字符串;
%u:無符號整數;
%%: 顯示%自身
其中還可以使用以下修飾符對格式符進行輸出格式的整理:
#[.#]:第一個#數字控制格式符顯示的寬度;第二個#數字表示格式符顯示的內容的精確度,只顯示最大長度為#的格式符內容;
-:左對齊,默認為右對齊;
+:顯示數值的符號;
如下示例:
[root@localhost ~]# awk -F: '{printf "The user:%-20s User ID:%15d\n",$1,$3} ' /etc/passwd
The user:root User ID: 0
The user:bin User ID: 1
The user:daemon User ID: 2
The user:adm User ID: 3
The user:lp User ID: 4
The user:sync User ID: 5
The user:shutdown User ID: 6
The user:halt User ID: 7
The user:mail User ID: 8
The user:operator User ID: 11
The user:games User ID: 12
The user:ftp User ID: 14
The user:nobody User ID: 99
The user:avahi-autoipd User ID: 170
The user:systemd-bus-proxy User ID: 999
The user:systemd-network User ID: 998
The user:dbus User ID: 81
The user:polkitd User ID: 997
The user:tss User ID: 59
The user:postfix User ID: 89
The user:sshd User ID: 74
-
條件表達式
awk命令的program語句也支持通過條件表達式來判斷控制,其表達式支持常見的算術、賦值、比較等操作符,如:+,-,*,/,%,=,+=,>,<,~等等的操作符,也支持邏輯操作與或非,其格式為:
awk [optioins] '{selector?if-true-expression:if-false-expression;action statements}' /PATH/TO/SOMEFILE
如根據用戶ID判斷對應用戶是系統用戶還是普通用戶:
[root@localhost ~]# awk -F: '{$3>=1000?usertype="this is a common user.":usertype="This is a system user.";printf "%20s:%-s\n",$1,usertype}' /etc/passwd
root:This is a system user.
bin:This is a system user.
daemon:This is a system user.
adm:This is a system user.
lp:This is a system user.
sync:This is a system user.
shutdown:This is a system user.
halt:This is a system user.
mail:This is a system user.
operator:This is a system user.
games:This is a system user.
ftp:This is a system user.
nobody:This is a system user.
pegasus:This is a system user.
avahi-autoipd:This is a system user.
ods:This is a system user.
systemd-bus-proxy:This is a system user.
systemd-network:This is a system user.
dbus:This is a system user.
polkitd:This is a system user.
sssd:This is a system user.
apache:This is a system user.
三、使用案例
- 格式化打印當前系統的用戶列表
[root@localhost ~]# awk -F: 'BEGIN{print "User lists"};{printf "User:%-25s\n",$1};END{print "This is the end."}' /etc/passwd
User lists
User:root
User:bin
.....
User:nologin
User:hadoop
This is the end.
[root@localhost ~]#
- 搜索打印以/bin/bash為默認shell的用戶信息:
[root@localhost ~]# awk -F: '$7~/.*bash\>/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
amandabackup:x:33:6:Amanda user:/var/lib/amanda:/bin/bash
postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash
centos:x:1001:1001::/home/centos:/bin/bash
federo:x:1002:1002::/home/federo:/bin/bash
counter:x:1003:1004::/home/counter:/bin/bash
charlie:x:1004:1005::/home/charlie:/bin/bash
Jone:x:1006:1007::/Jone:/bin/bash
Williom:x:1200:1005::/home/Williom:/bin/bash
mageia:x:1100:1100::/home/linux:/bin/bash
bash:x:2003:2003::/home/bash:/bin/bash
testbash:x:2004:2004::/home/testbash:/bin/bash
basher:x:2005:2005::/home/basher:/bin/bash
hadoop:x:2007:2007::/home/hadoop:/bin/bash
- 獲取系統網卡的Ip地址
[root@localhost ~]# ifconfig | awk '/inet\>/{print $2}'
188.88.88.42
127.0.0.1
192.168.122.1
- 對比兩個文件的內容
[root@localhost tmp]# cat a.sh
hello,world
i am charlie
this is my linux
magedeu
[root@localhost tmp]# cat b.sh
1
hello,world
2
i am charlie
3
this is my linux
4
magedeu
[root@localhost tmp]# awk 'FNR==NR{a[$0];next}{if($0 in a)print $0}' a.sh b.sh
hello,world
i am charlie
this is my linux
magedeu
上述awk命令在FNR和NR的等式成立的時候,將文件a.sh每行的內容作為數組a下標,然后執行next跳過后續if判斷語句;當FNR和NR的等式不成立的時候,不執行a[$0];next,執行后面的if語句,判斷b.sh中的每行內容是否為a數組中的元素下標,是的話就打印該行信息。
同理,利用取反找出不同的行:
[root@localhost tmp]# awk 'FNR==NR{a[$0];next}{if (!($0 in a))print $0}' a.sh b.sh
1
2
3
4
- 從文件中讀取program語句執行awk命令
這里以上面文件對比的命令為例:
[root@localhost tmp]# cat awk.sh
FNR==NR{
a[$0];
next
}
{
if (!($0 in a))
print $0
}
[root@localhost tmp]# awk -f awk.sh a.sh b.sh
1
2
3
4
如有錯誤,歡迎指點~