正則之Awk
1.什么是awk:
awk不僅僅是一個文本處理工具,同時也是一門編程語言,
是linux上功能最強大的數(shù)據(jù)處理工具之一。
2.awk 語法格式:
awk [options] 'commands' filenames
awk [options] -f awk-script-file filenames
處理的文件是/etc/hosts 總共三行
BEGIN 行處理前動作 {}行處理中 END行處理后
BEGIN{print 1/2} {print "OK"} END{print "Over"}
? ? 0.5? ? ? ? ? ? ok? ? ? ? ? ? GameOver
? ? ? ? ? ? ? ? ? ? ?ok
? ? ? ? ? ? ? ? ? ? ?ok
#命令 command
行處理前? ? ? 行處理? ? ? ? ? 行處理后
BEGIN{}? ? ? ? {}? ? ? ? ? ? ? END{}
#BEGIN發(fā)生在讀文件之前
[root@Shell ~]# awk 'BEGIN{print 1/2}'
0.5
#BEGIN在行處理前,修改字段分隔符
[root@shell ~]# awk 'BEGIN{FS=":"} {print $1}' /etc/passwd
#BEGIN在行處理前,修改字段讀入和輸出分隔符
[root@shell ~]# awk 'BEGIN{FS=":" OFS="---"}{print $1,$2}' /etc/passwd
#示例:
[root@shell ~]# awk 'BEGIN{print 1/2} {print "ok"} END{prrint "Game Over"}' /etc/hosts
0.5
ok
ok
ok
Game Over
=========================================
3.awk 命令格式:
#示例1,匹配awk 'pattern' filename
[root@shell ~]# awk '/root/' /etc/passwd
#示例2,處理動作 awk '{action}' filename
[root@shell ~]# awk -F:'{print $1}' /etc/passwd
=========================================
示例3,匹配+處理動作 awk 'pattern {action}' filename
[root@shell ~]# awk -F ':' '/root/{print $1,$3}' /etc/passwd
[root@shell ~]# awk 'BEGIN{FS=":"} /root/{print $1,$3}' /etc/passwd
示例4:判斷大于多少則輸出什么內(nèi)容 command |awk 'pattern {action}'
[root@shell ~]# df |awk '/\/$/ {if($3>50000)print $4}'
4.Awk工作原理:
# awk -F:'{print $1,$3}' /etc/passwd
1.awk將文件中的每一行作為輸入,并將每一行賦值給內(nèi)部變量$0,以換行符結(jié)束。
2.awk開始進行字段分隔,每個字段存儲在已編號的變量中,從$1開始[默認空格分隔]
3.awk默認字段分隔符是由內(nèi)部FS變量來確定,可以使用-F修訂。
4.awk行處理時使用了print函數(shù)打印分割后的字段。
5.awk在打印后的字段加上空格,因為$1,$3之間有一個逗號,逗號被映射至OFS內(nèi)部變量中,
稱為輸出字段分隔符。OFS默認為空。
6.awk輸出之后,將從文件中獲取另一行,并將其存儲在$0中,覆蓋原來的內(nèi)容,
然后將新的字符串分隔成字段并進行處理。該過程將持續(xù)到所有行處理完畢。
=========================================
例子1:
[root@shell ~]# cat awk_file.txt
ll 1989 55 56 63
kk 1990 60 57 64
hh 1991 70 58 65
jj 1992 80 59 66
mm 1993 90 60 67
1)awk指定多個分隔符,awk默認以空白行作為分隔符
#1.如何查看文件中的第一列:
[root@shell ~]# awk '{print $1}' awk_file.txt
ll
kk
hh
jj
mm
#2.如果有的文件不是以空格為分隔符怎么辦?
比如:/etc/passwd
[root@shell ~]# awk -F ":" '{print $2}' awk_file.txt
1989 55 56 63
1990 60 57 64
[root@shell ~]# awk -F "[: ]" '{print $2}' awk_file.txt
1989
1991
1992
1993
1994
=========================================
#[: ]+
? 1.連續(xù)的多個冒號當(dāng)一個分隔符
? 2.連續(xù)的多個空格當(dāng)一個分隔符
? 3.連續(xù)空格和冒號也當(dāng)做一個分隔符
"#[: \t]+"
? 4.連續(xù)空格和tab也當(dāng)做一個分隔符
? 5.連續(xù)tab也當(dāng)做一個分隔符
? 6.連續(xù)的冒號空格tab都算一個分隔符
===================================
例子2:
統(tǒng)計一行里有多少個數(shù)量,一共5個
[root@shell ~]# awk '{print NF}' awk_file.txt
5
5
5
5
5
======================================
1.awk內(nèi)置變量NF,保存每行的最后一列
#1.通過print打印,NF和$NF,你發(fā)現(xiàn)了什么?
[root@shell ~]# awk '{print NF,$NF}' awk_file.txt
5 63
5 64
5 65
5 66
5 67
#2.使用$NF為什么就能成功?(因為NF變量保存的是每一行的最后一列)
[root@shell ~]# awk '{print $NF}' awk_file.txt
63
64
65
66
67
#3.如果一個文件很長,靠數(shù)列數(shù)需要很長的時間,
那么如何快速打印倒數(shù)第二列?
[root@shell ~]# awk '{print $(NF-1)}' awk_file.txt
56
57
58
59
60
2)awk內(nèi)置變量NR,表示記錄行號
#1.使用pring打印NR,會發(fā)現(xiàn)NR會記錄每行文件的行號
[root@shell ~]# awk '{print NR,$0}' awk_file.txt
1 ll 1989 55 63
2 kk 1990 60 64
--------------------------------------------
#2.[root@shell ~]# awk 'NR==3{print $0}' awk_file.txt
hh 1991 70 58 65
#3.那如果我們想打印第二行到第三行的內(nèi)容怎么辦?
[root@shell ~]# awk 'NR>1&&NR<4 {print NR,$0}' awk_file.txt
2 kk 1990 60 57 64
3 hh 1992 70 58 65
#4.那如果只想打印第三行,該怎么辦?
[root@shell ~]# awk 'NR==3 {print NR,$00}' awk_file.txt
3 hh 1992 70 53 63
#5.那如果既想打印第三行,又想打印第一列?
[root@shell ~]# awk 'NR==3 {print NR,$1}' awk_file.txt
3 hh
===============================================
4.awk內(nèi)置變量,$0保存當(dāng)前記錄的內(nèi)容
[root@shell ~]#? awk '{print $0}' /etc/passwd?
5.awk內(nèi)置變量,F(xiàn)S指定字段分隔符,默認是空格?
#以冒號作為字段分隔符:
[root@shell ~]#? awk -F:'/root/{print $1,$3}' /etc/passwd
[root@shell ~]#? awk '{BEGIN{FS=":"}? {print $1,$3} '??/etc/passwd
內(nèi)置變量
NF? ? ? #記錄每行內(nèi)容的最后一列,通常記錄的是一個整數(shù)
NR? ? ?#記錄行號
FS? ? ?#指定字段分隔符
OFS? #指定輸出字段分隔符
$0? ? ?#代表每行的所有內(nèi)容
$1,$2? #指定字段分隔符后,每列的內(nèi)容
print? ?#輸出內(nèi)容
printf? #格式化輸出
===============================================
5.awk模式匹配與動作處理
awk語句都由模式和動作組成,模式部分動作語句何時觸發(fā)事件,如果省略模式部分,動作將時刻保持執(zhí)行狀態(tài),模式可以是條件語句或復(fù)合語句或正則表達式。
(1)正則表達式
#匹配記錄(整行)
[root@shell ~]# awk '/^root/' /etc/passwd?
#匹配字段,匹配操作符(~ !~)
[root@shell ~]#? awk '$1~/^root/' /etc/passwd
(2)條件表達式
[root@shell ~]# awk -F: '{if($3>300) print $0}' /etc/passwd
(3)條件判斷:
//統(tǒng)計系統(tǒng)用戶數(shù)量
[root@shell ~]#? awk -F: '{ if($3>0 && $3<1000){i++}} END {print i}' /etc/passwd
[root@shell ~]#? awk -F: '{ for(i=1;i<=10;i++) {print $0} }' passwd