awk(gawk)


  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  輸出時,需要指定輸出格式。

 

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交互

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM