1. 程式人生 > >Linux運維三劍客awk必會知識--模式與操作、內自變量、語句塊、數組

Linux運維三劍客awk必會知識--模式與操作、內自變量、語句塊、數組

三劍客 awk linux 運維 數組

Linux命令之三劍客awk
awk簡介
awk是三劍客中的老大,awk強大之處在於,它不僅僅是命令,還是一門語言,功能非常強大。報告生成器,格式化後顯示,可以自定義函數;awk的處理對象是記錄與字段(域)。
awk處理數據的原理
讀取到數據後,首先將數據分片,默認是以空格為分隔符,分片後給每個分片引用位置變量參數,然後按照awk命令的條件打印
技術分享圖片
記錄與字段
在講awk參數、內置變量、數組之前,首先講一下什麽是記錄,什麽是字段?字段很好理解,就是默認以空格為分割符分片後的區域,每個區域就是一個字段,就像上面的$1就是一個字段。
記錄,這個可能有點繞,暫時可以先了解一下,後面講到內置變量的時候,再結合例子來了解。awk處理對象是記錄和域(字段),而不是我們常說的行,讀取的文本是一連串的字符記錄,默認每條記錄的結束標誌是換行符“\n”,而這個結束標標誌是可以改變的,在後面的awk內置變量中就能了解到。
awk語法
awk [options] ‘{print item}‘ file1,file2...【也可以是某條命令的輸出結果】
【item可以是位置參數,如$1;或者是字符串,需要用“”引起來;item與item之間用“,”逗號隔開】
awk命令時由模式(pattern)和操作(action)組成
技術分享圖片
模式(pattern)
模式可以是以下任意一種:
1、正則表達式
當在awk中使用這種正則時:匹配其前字符多少次時,需要指定參數:--posix或者--re-interval,否則不能使用這種模式。

[root@bogon tmp]# cat awktest1

one#two#three num

zhangsan nan
lisi nv

wangwu nan
laowang nan

[root@bogon tmp]# 
[root@bogon tmp]# awk ‘/^[^$]/‘ awktest1  ^在[]裏面表示不匹配之意
one#two#three num
zhangsan nan
lisi nv
wangwu nan
laowang nan
[root@bogon tmp]#
[root@bogon tmp]# awk ‘/^lao/{print $2}‘ awktest1
nan
[root@bogon tmp]#

x{m}:x重復m次
x{m,}:x至少重復m次
x{,m}:x至多重復m次
x{m,n}:x至少重復m次,但不超過n次

[root@bogon tmp]# cat awk1
root
rrtt
good
[root@bogon tmp]# awk --posix ‘/o{2}/{print $0}‘ awk1
root
good
[root@bogon tmp]#

2、關系表達式:使用運算符進行操作,可以是字符串或數字的比較測試

、<、=、>=、<=

[root@bogon tmp]# awk ‘NR&gt;=2{print $0}‘ awk1
rrtt
good
[root@bogon tmp]#

3、模式匹配正則表達式:用運算符~(匹配)和~!不匹配
[root@localhost ~]# ifconfig enp0s3 | awk -F "[: ]*" ‘$2~/inet$/ {print $3}‘
4、還能匹配類似sed的地址範圍

[root@bogon tmp]# cat awk1
root
rrtt
good
hello
nihao
nizaiganma
[root@bogon tmp]#
[root@bogon tmp]# awk ‘NR==2,NR==4{print $0}‘ awk1  
rrtt
good
hello
[root@bogon tmp]#
[root@bogon tmp]# awk ‘/^rr/,NR==3{print $0}‘ awk1 
rrtt
good
[root@bogon tmp]#

5、BEGIN 語句塊, END語句塊
操作(action)
操作由一個或多個命令、函數、表達式組成,之間由換行符或分號隔開,並位於大括號內,主要部分是:變量或數組賦值、輸出命令、內置函數、控制流語句。比如:print函數,’{print $1}’
awk命令處理流程圖
如果沒有定義BEGIN與END語句塊,那麽就不會執行BEGIN、END語句塊。
技術分享圖片

awk參數
-F re:允許awk更改其字段分隔符
-v var=$v 把v值賦值給var,如果有多個變量要賦值,那麽就寫多個-v,每個變量賦值對應一個-v
e.g. 要打印文件a的第num行到num+num1行之間的行,
awk -v num=$num -v num1=$num1 ‘NR==num,NR==num+num1{print}‘ a
-f progfile:允許awk調用並執行progfile程序文件,當然progfile必須是一個符合awk語法的程序文件。
-F參數等同於" -v FS=要給FS賦的值 " 【即指定字段分隔符,如-F “:”等於-v FS=:,指定以冒號為分隔符】
--posix或—re-interval:某些正則模式下,需要指定該參數來使用正則(常用的是-F與--posix)
awk內置變量
$n:當前記錄的第n個字段,比如n為1表示第一個字段,n為2表示第二個字段
$0:這個變量包含執行過程中當前行的文本內容【整行】
NR:表示記錄數,在執行過程中對應於當前的行號
FS:字段分隔符(默認是空格)
OFS:輸出字段分隔符(默認是空格)
NF($NF ):表示字段數,在執行過程中對應於當前的字段數;print $NF 打印一行中最後一個字段
ORS:輸出記錄分隔符(默認值是換行符)
RS:記錄分隔符(默認是換行符)
ARGC:命令行參數的數目
ARGIND:命令行中當前文件的位置(從0開始算)
ARGV:包含命令行參數的數組
CONVFMT:數字轉換格式(默認值為%.6g)
ENVIRON:環境變量關聯數組
ERRNO:最後一個系統錯誤的描述
FIELDWIDTHS:字段寬度列表(用空格鍵分隔)
FILENAME:當前輸入文件的名
FNR:同NR,但相對於當前文件
IGNORECASE:如果為真,則進行忽略大小寫的匹配
OFMT:數字的輸出格式(默認值是%.6g)
RSTART:有match函數所匹配的字符串的第一個位置
RLENGTH:由match函數所匹配的字符串的長度
SUBSEP:數組下標分隔符(默認值是34)
BEGIN:awk命令執行前執行該操作,可在這定義變量(內置變量)
END:awk命令執行完成後執行該操作,可用來最後輸出結果,統計信息,計算空行等。
常用內置變量詳解:
NR,NF ,$n,FS,OFS,RS,ORS
實驗環境:

[root@bogon tmp]# cat awktest
Hello 1
      2
      3 
I am a teacher  4
I like basketball  5

$n 當前記錄(行)的第n個字段(位置變量),默認以空格為分隔符,“$0”表示整行

[root@bogon tmp]# awk ‘{print $0}‘ awktest
Hello 1
      2
      3 
I am a teacher  4
I like basketball  5
[root@bogon tmp]#
[root@bogon tmp]# awk ‘{print $1}‘ awktest 
Hello
2
3
I
I
[root@bogon tmp]#

NR:表示輸入記錄數(行號)

[root@bogon tmp]# awk ‘{print NR,$0}‘ awktest
1 Hello 1
2       2
3       3 
4 I am a teacher  4
5 I like basketball  5
[root@bogon tmp]# awk ‘NR==4{print NR,$0}‘ awktest
4 I am a teacher  4
[root@bogon tmp]#

NF:表示每行輸入字段數
什麽是字段?
例如:第4行“I am a teacher”
默認是以空格為分隔符,“I”第一個字段,“am”第二個字段,依此類推,第4行共4個字段
“$NF”表示行的最後一個字段

[root@bogon tmp]# awk ‘{print NF,$0}‘ awktest
2 Hello 1
1       2
1       3 
5 I am a teacher  4
4 I like basketball  5
[root@bogon tmp]# awk ‘{print $NF}‘ awktest 
1
2
3
4
5
[root@bogon tmp]#

FS或-F:輸入字段分隔符,默認為空格

[root@bogon tmp]# awk -F ":" ‘NR==1{print $2}‘ /etc/passwd 
x
[root@bogon tmp]# awk ‘BEGIN{FS=":"}NR==1{print $2}‘ /etc/passwd         
x
[root@bogon tmp]#

OFS :輸出字段分隔符,默認為空格
$0默認是不會改變行的結果的,所以想要使用$0輸出,又想改變其結果,那麽就需要在前面給它個動作;一般很少使用$0輸出

[root@bogon tmp]# awk ‘BEGIN {FS=" ";OFS="@"}{print $0}‘ awktest   
Hello 1
      2
      3 
I am a teacher  4
I like basketball  5
 [root@bogon tmp]# awk ‘BEGIN {FS=" ";OFS="@"}$1=$1{print $0}‘ awktest            給個動作$0,使其改變輸出結果
Hello@1
2
3
I@am@a@teacher@4
I@like@basketball@5
[root@bogon tmp]# awk ‘BEGIN {FS=" ";OFS="@"}{print $1,$2,$3}‘ awktest    
Hello@1@
2@@
3@@
I@am@a
I@like@basketball
[root@bogon tmp]#
[root@bogon tmp]# awk ‘BEGIN{FS="[:/]";OFS="#"}NR==1{print $1,$NF}‘ /etc/passwd
root#bash
[root@bogon tmp]#

RS:輸入記錄行分隔符,默認為換行符(讀入時候的分隔符,意思就是一某個符號作為行的分隔符來劃分行,默認是換行符\n)
awk處理對象是記錄和域(字段),而不是我們常說的行,讀取的文本是一連串的字符記錄,默認每條記錄的結束標誌是換行符“\n”。

[root@bogon tmp]# awk ‘{print NR,$0}‘ awk.txt 
1 root:x:0:0:root:/root:/bin/bash\n
2 bin:x:1:1:bin:/bin:/sbin/nologin\n
[root@bogon tmp]# awk ‘BEGIN{RS="/"}{pritn NR,$0}‘ awk.txt            現在把劃分行的分隔符改為“/”,存在“/”就是回車換行
awk: BEGIN{RS="/"}{pritn NR,$0}
awk:                       ^ syntax error
[root@bogon tmp]# awk ‘BEGIN{RS="/"}{print NR,$0}‘ awk.txt   
1 root:x:0:0:root:
2 root:
3 bin
4 bash
bin:x:1:1:bin: 因為\n已經不是記錄分隔符,所以這行不會被算作記錄行
5 bin:
6 sbin
7 nologin
        因為\n已經不是記錄分隔符,所以這行不會被算作記錄行
[root@bogon tmp]#

[root@bogon tmp]# cat ricky 
1\n
2\n
3\n
1\n
4\n
5\n
1\n
6\n
7\n
[root@bogon tmp]# awk ‘BEGIN{RS="1"}{print $1,$2,$3}‘ ricky 
    1作為分隔符,所空行
2 3 \n不再是分隔符,所以2與3之間的\n,成為了一個空格存在
4 5 
6 7 
[root@bogon tmp]#

ORS:輸出記錄行分隔符,默認為換行符(輸出時的分隔符),是RS的逆向操作
把下面的文本變成一行

one\n
two\n
three\n
[root@localhost tmp]# awk ‘BEGIN{ORS=" "}{print $0}‘ awktest2 (把換行符"\n"轉變為空格)   
one two three [root@localhost tmp]# 

BEGIN語句塊
awk命令執行前執行該操作,可在這定義變量(內置變量)

[root@bogon tmp]# awk ‘BEGIN{FS=":"}NR==1{print $2}‘ /etc/passwd         
x
[root@bogon tmp]#

END語句塊
awk命令執行完成後執行該操作,可用來最後輸出結果,統計信息,計算空行等。
例1:
統計文件裏面的空行數量
grep實現

[root@bogon tmp]# grep -c "^$" /etc/init.d/sshd (-c計算符合條件的行數)
20 
[root@bogon tmp]#

awk實現

[root@bogon tmp]# awk ‘/^$/{a++;print a}‘ /etc/init.d/sshd (調試,每次匹配都輸出a的值) 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@bogon tmp]# awk ‘/^$/{a++}END{print a}‘ /etc/init.d/sshd(統計信息,在awk命令結束後輸出a的值,“/^$/{a++},條件匹配一次,變量a的值加1”)  
20
[root@bogon tmp]#

例2:
找出變量環境$PATH中,所有只有三個任意字符的命令,例如tee,並講他們重定向到command.txt,要求一行顯示一個,並在文件尾部統計他們的個數。

[root@bogon tmp]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/bin:/root/bin
[root@bogon tmp]# echo $PATH | tr ":" "\n"
/usr/local/sbin
/usr/local/bin
/sbin
/bin
/usr/sbin
/usr/bin
/root/bin
/bin
/root/bin
[root@bogon tmp]# find $(echo $PATH | tr ":" "\n") -type f -name "???" 2>/dev/null |awk ‘{a++}{print $0}END{print "result:"a}‘ >>command.txt (?在命令當中數通配符,任意一個字符;
? 通配符用戶匹配文件名;而在正則中表示匹配其前字符0次或1次)
[root@bogon tmp]# cat command.txt 
/sbin/cbq
/sbin/lvm
/sbin/sln
/sbin/arp
/bin/env
/bin/raw
/bin/cat
/bin/cut
/bin/rpm
/bin/sed
/bin/tar
/bin/pwd
/usr/sbin/lid
/usr/sbin/zic
/usr/bin/lua
/usr/bin/grn
/usr/bin/dir
/usr/bin/who
/usr/bin/tac
/usr/bin/seq
/usr/bin/xxd
/usr/bin/cpp
/usr/bin/cmp
/usr/bin/idn
/usr/bin/fmt
/usr/bin/yum
/usr/bin/pic
/usr/bin/tic
/usr/bin/eqn
/usr/bin/toe
/usr/bin/man
/usr/bin/tee
/usr/bin/ptx
/usr/bin/ldd
/usr/bin/c89
/usr/bin/s2p
/usr/bin/a2p
/usr/bin/sum
/usr/bin/sar
/usr/bin/vim
/usr/bin/top
/usr/bin/tbl
/usr/bin/tty
/usr/bin/c99
/usr/bin/gcc
/usr/bin/rev
/usr/bin/col
/usr/bin/yes
/usr/bin/cal
/bin/env
/bin/raw
/bin/cat
/bin/cut
/bin/rpm
/bin/sed
/bin/tar
/bin/pwd
result:57
[root@bogon tmp]#

數組
數組的結構
技術分享圖片
技術分享圖片

處理以下文件內容,將域名取出並根據域名進行統計數排序處理
http://www.baidu.com/index.html
http://www.baidu.com/1.html
http://post.baidu.com/index.html
http://mp3.baidu.com/index.html
http://www.baidu.com/3.html
http://post.baidu.com/2.html

方案一:

[root@bogon tmp]# awk ‘BEGIN{FS="/"}{print $3}‘ baidu.txt | sort | uniq -c
      1 mp3.baidu.com
      2 post.baidu.com
      3 www.baidu.com
[root@bogon tmp]#

方案二:

[root@bogon tmp]# awk ‘BEGIN{FS="/"}{array[$3]++}END{for (key in array)print key,array[key]}‘ baidu.txt 
post.baidu.com 2
www.baidu.com 3
mp3.baidu.com 1
[root@bogon tmp]#

分析數組
array[$3]++ > array[$3]= array[$3]+1=0+1 (array[$3]初始值為0)
array[www.baidu.com]++ >0+1 1
array[www.baidu.com]++ >1+1 2
array[post.baidu.com]++ >0+1 1
array[mp3.baidu.com(數組名)]++ >0+1 1(數組的值)
array[www.baidu.com]++ >2+1 3
array[post.baidu.com]++ >1+1 2

for key in array (代表數組名)
for key in post.baidu.com www.baidu.com mp3.baidu.com

array[key]
array[post.baidu.com]++ >1+1 2
array[www.baidu.com]++ >2+1 3
array[mp3.baidu.com]++ >0+1 1

總結
記錄與字段
模式:正則;模式匹配正則;sed地址範圍;關系表達式
操作
參數:--posix或—re-interval
內置變量:FS;OFS;RS;ORS;NF($NF);$n($0)
語句塊:BEGIN;END
數組

Linux運維三劍客awk必會知識--模式與操作、內自變量、語句塊、數組