awk,逐行處理文本內容。Linux里的awk其實是“gawk”。
使用格式:
awk [選項] '模式匹配 {命令 命令參數}' file1, file2, ……
支持的選項 | 說明 |
---|---|
-f program-file --file program-file |
從文件接收 awk指令,可以同時指定多個文件 |
-F fs --field-separator fs |
指定(fs)列分隔符 |
-v var=value --assign var=value |
為 BEGIN 塊定義變量var,指定其值為value |
-d[file] --dump-variables[=file] |
demo,ipaddress倆文件的內容是環網櫃、柱上開關櫃的主、備ip地址。分別以制表符、冒號分割。
$ cat demo RingNetwork 181.36.1.8 182.36.4.8 Switch 181.32.1.22 182.36.4.42 Switch 181.32.1.23 182.36.4.43 $ cat ipaddress R:181.36.1.8:182.36.4.8 S:181.32.1.22:182.36.4.42 S:181.32.1.23:182.36.4.43
命令:
print 打印輸出,參數之間使用逗號分隔。
printf 輸出時,需要指定輸出格式。
格式 鉚定符 |
效果說明 | 例子(頁面最下邊) |
---|---|---|
%c | 打印成 ascii 碼表的“char”形式 |
2.1 |
%s | 輸出字符串 |
2.2 |
%d, %i | 十進制數的整數部分 |
2.3 |
%o | 無符號八進制數的整數部分 |
2.4 |
%x, %X | 同上,大小的區別表示[a-f],[A-F] |
2.5 |
%u | 無符號的十進制數的整數部分 | |
%f | 浮點數 |
2.6 |
%% | 輸出%,相當於\\輸出反斜線一樣 |
|
%10s | 預留10個字符位置,右對齊 |
|
%-10s |
左對齊顯示 |
常見變量:
FS 輸入列分割符
OFS 輸出列分隔符
RS 輸入行分割符
ORS 輸出行分割符
NF 記錄數(當前處理的)
NR 行數(當前處理)
FNR 行數(當前文件)
1 輸出文本 print
1.1 輸出指定列信息
取出每個設備的主ip地址信息
$ awk '{print $2}' demo 181.36.1.8 181.32.1.22 181.32.1.23
1.2 列分隔符
1.2.1 列的引用表示
$1、$2……分別表示當前處理行的第一列、第2列……。$0表示當前行所有列。
$ awk '{print $0}' demo RingNetwork 181.36.1.8 182.36.4.8 Switch 181.32.1.22 182.36.4.42 Switch 181.32.1.23 182.36.4.43 $ awk '{print $1,$2,$3}' demo RingNetwork 181.36.1.8 182.36.4.8 Switch 181.32.1.22 182.36.4.42 Switch 181.32.1.23 182.36.4.43
輸出awk處理的文件的列數。
$ awk '{print NF}' demo 3 3 3 $ awk '{print NF}' ipaddress 1 1 1 $ awk '{print NF}' demo ipaddress 3 3 3 1 1 1
1.2.2 輸出列分割符
awk默認輸出分隔符是空格,可以通過變量“OFS”修改,需要使用雙引號。
$ awk 'BEGIN{OFS=":"} {print $1,$2,$3}' demo RingNetwork:181.36.1.8:182.36.4.8 Switch:181.32.1.22:182.36.4.42 Switch:181.32.1.23:182.36.4.43
1.2.3 輸入列分割符
awk以空白符作為默認輸入分割符,就算分割不是制表符,而是某些個空格符也一樣能准確取到主ip。同時,還可以修改默認輸入分割符,通過變量“FS”顯式指定分割符為空格。
awk 'BEGIN{FS=":"} {print $1,$2,$3}' ipaddress R 181.36.1.8 182.36.4.8 S 181.32.1.22 182.36.4.42 S 181.32.1.23 182.36.4.43
或者在選項“F”里指定分隔符。
$ awk -F: '{print $2}' ipaddress 181.36.1.8 181.32.1.22 181.32.1.23
1.3 行分隔符
輸出當前處理的行數
$ awk '{print NR}' demo ipaddress 1 2 3 4 5 6 $ awk '{print FNR}' demo ipaddress 1 2 3 1 2 3
2 輸出文本 printf
2.1 驗證printf命令的%c格式,是把ASCII的Dec列內容轉換成Char列內容。(是不是有點像發電報一樣)
[root@hp430G2 demo]# cat num 72 101 108 108 111 [root@hp430G2 demo]# awk '{printf("%c", $1)}END{printf("\n")}' num Hello [root@hp430G2 demo]# cat num 72 101 108 108 111 [root@hp430G2 demo]# awk '{printf("%c%c%c%c%c", $1,$2,$3,$4,$5)}END{printf("\n")}' num Hello
因為,printf默認不換行,所有要借助END,而且順便借助不換行完成單詞的拼接。而且,模式數量必須與變量數量(列)對應起來。
2.2 驗證printf命令的%s格式
[root@hp430G2 demo]# cat alpha Hello [root@hp430G2 demo]# awk '{printf("%s", $1,$2,$3,$4,$5)}END{printf("\n")}' alpha Hello
2.3 驗證printf命令的%d、%i格式
[root@hp430G2 mag37]# cat int 3.1415926 [root@hp430G2 mag37]# awk '{printf("%i", $1)}END{printf("\n")}' int 3 [root@hp430G2 mag37]# awk '{printf("%d", $1)}END{printf("\n")}' int 3
2.4 驗證printf命令的%o指定輸出八進制格式。
[root@hp430G2 mag37]# cat oct 181.37.1.42 182.37.4.42 [root@hp430G2 mag37]# awk -F. '{printf("%o.%o.%o.%o\n", $1,$2,$3,$4)}' oct 265.45.1.52 266.45.4.52
2.5 驗證printf命令的%X、%x指定輸出十六進制格式,分別輸出字母部分的大小寫。
[root@hp430G2 mag37]# cat hex 181.37.1.42 182.37.4.42 [root@hp430G2 mag37]# awk -F. '{printf("%x.%x.%x.%x\n", $1,$2,$3,$4)}' oct b5.25.1.2a b6.25.4.2a [root@hp430G2 mag37]# awk -F. '{printf("%X.%X.%X.%X\n", $1,$2,$3,$4)}' oct B5.25.1.2A B6.25.4.2A
2.6 驗證%f,沒搞明白,這里輸出分割符不能成功指定。
[root@hp430G2 mag37]# cat float 181.37 1.42 182.37 4.42 [root@hp430G2 mag37]# awk '{printf("%F %F\n",$1,$2)}' float 181.370000 1.420000 182.370000 4.420000
可不可以這樣看,在使用了printf時,輸出控制的權利就完全交割了,變量被失效了。
3 數學運算
3.1 算術運算
BEGIN{ r=5 R=r*2 print R y=R*3.14 print y }
支持常見操作符:+ - * / ^ % =,分別表示加、減、乘、除、次方、取余數、賦值。
3.2 條件運算
支持條件判斷:x < y、x <= y、x > y、x >= y、x == y、x != y、x ~ RE、x !~ RE、&&、||,比較字符串的大小關系、相同關系、匹配正則表達式、多個表達式之間的關系。以及條件表達式:?:
3.3 匹配運算
#!/bin/awk -f $1 ~ /^s/ {print}
* 注意與上邊例子中“print”命令使用“花括號”的位置。
4 模式匹配
4.1 邏輯匹配
輸出模式匹配的行;首列大於19、在7到11之間、等於12。
awk '$1>19 {print}' demo.txt awk '$1==12 {print}' demo.txt
下邊的命令,會使得輸出值發生變化;為輸出結果重新賦值。
awk '$1=12 {print}' demo.txt
4.2 使用正則表達式匹配
使用正則表達式匹配;大寫字母后面跟着小寫字母、文件大小為2開頭、取大小值
awk '/[[:upper:]][[:lower:]]/ {print}' demo.txt awk '/:..[[:space:]]*2/ {print}' demo.txt awk '/grep/ {print}' demo.txt
4.3 混合模式匹配
找出以兩個數字開頭、第4列大於40、並且包含一個大寫字母后邊跟着一個小寫字母的行。
awk '/^[[:digit:]]/ && $4>40 && /[[:lower:]]/ {print}' demo.txt awk '$1>7 && $1<11 {print}' demo.txt
4.4 區間模式
awk '/^8/,$4==37 {print}' new.txt
4.5 讀取數據文件之前的“BEGIN模式”“END”
由於“begin”塊內的命令是在讀取文件之前就開始執行的,所以這里的命令不能是操作文件數據的命令。通常可以用來初始化變量。執行順序就是從“BEGIN”開始,到“模式匹配階段的數據處理命令”,最后執行“END”。
awk 'BEGIN{print "This is all lines in new.txt."} {print}' new.txt
END模塊(這里的“BEGIN”、“END”必須是大寫的)
awk '{print} END{print "File is over."}' new.txt
在該模式下,awk變量的定義、賦值、引用。
[awk@h p]$ cat demo2.txt This is for test of awk's begin and end. [awk@h p]$ cat print.awk #!/bin/awk -f BEGIN{ print "begin" } {print} END{ print "end\nover" } [awk@h p]$ ./print.awk demo2.txt begin This is for test of awk's begin and end. end over
3 變量
變量 |
釋義 |
---|---|
$0 |
當前正在處理的記錄 |
$n |
第n個字段的值 |
NF |
當前處理記錄的字段數 |
NR |
當前已經讀入的記錄數 |
FILENAME |
正在處理的數據文件的名稱 |
FS |
字段分割符(默認空格、或制表符) |
RS |
記錄分割符(默認換行) |
NF表示字段數,更有用的可以得到最后一個字段(當每行不同字段時更有用)。可以獲取文件名、文件大小
[root@Rsync logs4developers]# tree -fh | grep "M" | awk '{print $NF ,$(NF-1)}'
3.1 普通變量
[awk@h p]$ cat demo1.awk #!/bin/awk -f BEGIN{ age=33 say_hello="hello" print age print say_hello [awk@h p]$ awk -f demo1.awk 33 hello
3.2 內置變量
[awk@h p]$ cat ip_port.txt 172.17.36.40:22,3306 10.134.1.4:22,1521 [awk@h p]$ awk 'BEGIN{FS=":"; RS="\n"; RS=""; ip="ip = "; port=" port = "} {print ip $1 port $2}' ip_port.txt ip = 172.17.36.40 port = 22,3306 ip = 10.134.1.4 port = 22,1521
4 使用腳本
4.1 在腳本中執行 awk 命令
[web@h p]$ cat my_awk.sh #!/bin/awk -f {print} [web@h p]$ ./my_awk.sh demo.txt
4.2 交互模式下的“文件結束符”
運行這個腳本
#!/bin/awk -f BEGIN{ exitpro="press <ctrl+d> exit the script." print "test is beginning." print exitpro print "=============================" } {print} END{ print "=============================" print "test is over." }
腳本運行后,終端等待輸入內容,輸入結束時需要給腳本文件發送“EOF”信號。按組合鍵“ctrl+d”退出(Windows平台“ctrl+z”)。
4.3 體會命令執行模式
運行這個腳本
#!/bin/awk -f { print print "Have two print." }
當命令“print”沒有“file“時,以交互模式執行;執行時這里也是需要“EOF”的,第一條命令執行結束后,執行下一條命令;但是“打印”命令始終是需要一個“EOF”的,而這個信號的接收不會影響后邊命令的執行。
看到上邊的例子,我會以為“需要在EOF是因為有個命令的緣故”。去掉腳本中的“print”命令,結果發現依然需要。不同之處在於沒有回顯。
在腳本執行時,添加一個“demo.txt”。發現腳本依然可以執行,說明 awk 在執行時,“pattern”、“actions”都可以不需要。
4.4 命令的執行順序
awk處理“file”時,按照“記錄”依次處理。其中的命令執行是每條命令執行完讀入的一條“記錄”下一條命令接着處理同樣一條“記錄”。
[awk@h p]$ cat demo.txt This is row1. This is row2. This is row3. [awk@h p]$ cat print-file.awk #!/bin/awk -f { print print } [awk@h p]$ This is row1. This is row1. This is row2. This is row2. This is row3. This is row3.
6 函數
6.1 字符串函數
函數 | 釋義 |
---|---|
index(s1,s2) | 返回 s2 在 s1 中的位置;返回值從“1”開始,“0”代表不存在 |
length(s1) | 返回字符串的長度;返回整數值 |
match(s1,RE) | 查找匹配正則表達式匹配的字符串;涉及變量“RSTART”,“RLENGTH” |
split(s1,array,sep) | 以“sep”分割“s1”后,返回“array” |
[awk@h p]$ awk 'add=index($0,"sunny") {print add}' demo.txt 1 [awk@h p]$ awk '{print index($0,"sunny")}' demo.txt 1 0
6.2 算術函數
函數 | 釋義 |
---|---|
int(x) | 返回整數部分 |
rand() | 反饋0~1之間的隨機數 |
srand([x]) | 反回一個基於“x”的隨機數 |
7 數組
7.1 數組的定義與引用
#!/bin/awk -f BEGIN{ port[1]=22 port[2]=3389 port[3]=10022 print port[1],port[2],port[3] }
7.2 數組遍歷
借用“for 循環”遍歷數組元素
8 流程控制
9 格式化輸出
10 shell交互