第10章:awk進階操作
第10章:awk進階操作
在第4章:查找與替換簡單的講解了awk的使用,本章介紹詳細講解awk的使用。awk是一個強大的文本分析工具,簡單的說awk就是把文件逐行的讀入,
以空格為默認分隔符將每行切片,切開的部分再進行各種分析處理。在shell腳本中文本處理功能awk功能其強大。
7.1、awk命令形式
awk命令在shell腳本基本形式通常由四部分組成: [-F|-f|-v] (參數選項)、BEGIN語句塊(初始化代碼塊)、pattern{commadns}(能夠使用模式匹配的通用語句塊)、END語句塊(結束代碼塊),這四部分是可選擇的,任意一部分都可以不出現在腳本中,後面三部分通常是被單引號或雙引號括起來,awk命令形式如下所示:
awk [-F|-f|-v] ‘BEGIN{ commands } /pattern/{ commands } END{ commands}’ filename
四部分分別代表意義:
[-F|-f|-v] 參數選項:-F指定分隔符,-f調用腳本,-v定義變量 如var=value。
BEGIN{ commands } 初始化代碼塊:在對第一行進行處理之前,初始化代碼,主要是引用全局變量,設置FS分隔符。
/pattern/{ commands } 匹配代碼塊和命令代碼塊:/pattern/匹配代碼塊,pattern可以是字符串或正則表達式;{ commands } 命令代碼塊,commadns可包含一條或多條命令。
END{ commands } 結尾代碼塊:在對每一行進行處理之後再執行的代碼塊,主要是進行最終的計算或輸出結尾摘要信息。
awk工作原理:
第一步:執行BEGIN{ commands }語句塊中的語句,可以選擇[-F|-f|-v]參數選項一起執行。
第二步:從文件或標準輸入(stdin)讀取一行,然後執行/pattern/{ commands }語句塊,它逐行掃描文件,從第一行到最後一行重復這個過程,直到文件全部被讀取完畢。
第三步:當讀至輸入流末尾時,執行END{ commands }語句塊。
BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,比如變量初始化、打印輸出表格的表頭等語句通常可以寫在BEGIN語句塊中,可以選擇[-F|-f|-v]參數選項一起使用,這兩部分是可選的。
pattern語句塊中的通用命令是最重要的部分,它也是可選的。如果沒有提供/pattern/語句塊,則默認執行{ commands },即打印每一個讀取到的行,awk讀取的每一行都會執行該語句塊。
END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如打印所有行的分析結果這類信息匯總都是在END語句塊中完成,它也是可選的。
範例:以#號為分格符,分別輸出兩行,$1代表第一個字段,$2代表第二個字段。
[[email protected] ~]# echo -e "A line 1#A line 2" | awk -F "#" ‘BEGIN{ print "Start" } {print $1 "\n" $2} END{ print "End" }‘
Start
A line 1
A line 2
End
7.2、awk內置變量
awk有許多內置變量用來設置環境信息,這些變量可以被改變,下面給出了最常用的一些變量。如下圖所示:
舉例:
Linux系統創建了一個測試文本list,後續部分範例操作會以文本list為測試文件,測試文本list內容如下:
[[email protected] home]# cat list
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 EAST Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post Road, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
範例1:$1顯示第一列,awk如果沒有指定分界符,默認以空格或制表符為分界符。
[[email protected] home]# awk ‘{print $1}‘ list
John
Alice
Orville
Terry
Eric
Hubert
Amy
Sal
知識點補充:$2代表第二列,以此類推,如果是$10以上,不能直接使用$10需要加上括號如:$(10)
範例2:$0輸出當前文本內容。
[[email protected] home]# awk ‘{print $0}‘ list
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 EAST Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post Road, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
範例3:使用NR統計文本中的行數,打印指定的行和列。
[[email protected] home]# awk ‘{print NR}‘ list
1
2
3
4
5
6
7
8
[[email protected] home]# awk ‘END{print NR}‘ list
8
[[email protected] home]# nl list | awk ‘NR==3{print}‘
3 Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
[[email protected] home]# nl list | awk ‘NR==3{print $2}‘
Orville
範例4:”/ /”模式,主要用於匹配正則表達式
[[email protected] home]# awk ‘/MA/‘ list
John Daggett, 341 King Road, Plymouth MA
Eric Adams, 20 Post Road, Sudbury MA
Sal Carpenter, 73 6th Street, Boston MA
[[email protected] home]# awk ‘/MA/ {print $1}‘ list
John
Eric
Sal
範例5:選項 –F 指定字段的分隔符
[[email protected] home]# awk -F ‘,‘ ‘{print $1 $2}‘ list
John Daggett 341 King Road
Alice Ford 22 EAST Broadway
Orville Thomas 11345 Oak Bridge Road
Terry Kalkas 402 Lans Road
Eric Adams 20 Post Road
Hubert Sims 328A Brook Road
Amy Wilde 334 Bayshore Pkwy
Sal Carpenter 73 6th Street
[[email protected] home]# awk -F ‘,‘ ‘{print $1;print $2}‘ list
John Daggett
341 King Road
Alice Ford
22 EAST Broadway
Orville Thomas
11345 Oak Bridge Road
Terry Kalkas
402 Lans Road
Eric Adams
20 Post Road
Hubert Sims
328A Brook Road
Amy Wilde
334 Bayshore Pkwy
Sal Carpenter
73 6th Street
知識點補充:多重命令使用分號隔開。
範例6:選項 –f 直接調用腳本或文本裏的內容
[[email protected] home]# cat filename
/MA/{print "第" NR "行:" "內容:" $0}
[[email protected] home]# awk -f filename list
第1行:內容:John Daggett, 341 King Road, Plymouth MA
第5行:內容:Eric Adams, 20 Post Road, Sudbury MA
第8行:內容:Sal Carpenter, 73 6th Street, Boston MA
範例7:內置變量NF,NF顯示文本每一行的字段數量,$NF顯示文本最後一列。
[[email protected] home]# awk ‘{print $NF}‘ list
MA
VA
OK
PA
MA
VA
CA
MA
[[email protected] home]# awk ‘{print NF}‘ list
7
7
8
8
7
7
8
7
範例8:借助-v選項,可以將變量的值傳遞給awk,有兩種傳遞方法。
方法一:
[[email protected] home]# cat test.sh
#!/bin/bash
var=1000
echo | awk -v vartable=$var ‘{print vartable}‘
[[email protected] home]# ./test.sh
1000
方法二:
[[email protected] home]# cat test.sh
#!/bin/bash
var1=1000
var2=2000
echo | awk ‘{print v1,v2}‘ v1=$var1 v2=$var2
[[email protected] home]# ./test.sh
1000 2000
範例9:向腳本傳遞參數
[[email protected] home]# cat test.sh
#!/bin/bash
#在awk命令中$1代表輸入行的第一列字段,而在shell腳本中$1代表命令行提供的第一個參數
#把shell腳本$1第一個參數賦值給var,再將var賦值給awk$1第一列字段
awk ‘$1=var‘ var=$1 list
[[email protected] home]# ./test.sh ABC
ABC Daggett, 341 King Road, Plymouth MA
ABC Ford, 22 EAST Broadway, Richmond VA
ABC Thomas, 11345 Oak Bridge Road, Tulsa OK
ABC Kalkas, 402 Lans Road, Beaver Falls PA
ABC Adams, 20 Post Road, Sudbury MA
ABC Sims, 328A Brook Road, Roanoke VA
ABC Wilde, 334 Bayshore Pkwy, Mountain View CA
ABC Carpenter, 73 6th Street, Boston MA
範例10:awk命令嵌套if判斷語句和for循環語句。
###判斷當前文件和目錄大於500字節的文件打印出文件和大小
[[email protected] home]# ls -l | awk ‘{if (($5>=500)) print "\n" "文件: " $9 "\n" "大小: " $5 "B" "\n"}‘
文件: lost+found
大小: 16384B
###判斷當前目錄文本大於300字節的文件打印出文件和大小
[[email protected] home]# ls -l | awk ‘{if (( $5>=300 && /^-/ )) print "\n" "文本: " $9 "\n" "大小: " $5 "B" "\n"}‘
文本: list
大小: 341B
文本: list.bak
大小: 341B
#把abcde字符串按順序逐個輸出
[[email protected] home]# echo "abcde" | awk -F ‘‘ ‘{for(i=1;i<=NF;i++) print $i}‘ filename
a
b
c
d
e
[[email protected] home]# echo "abcde" | awk -F ‘‘ ‘{for(i=NF;i>=1;i--) print $i}‘ filename
e
d
c
b
a
範例11:awk命令提供兩個函數用於完成字符串大小寫轉換,函數為小寫tolower()和大寫toupper()。
[[email protected] home]# awk ‘{print tolower($0)}‘ list
john daggett, 341 king road, plymouth ma
alice ford, 22 east broadway, richmond va
orville thomas, 11345 oak bridge road, tulsa ok
terry kalkas, 402 lans road, beaver falls pa
eric adams, 20 post road, sudbury ma
hubert sims, 328a brook road, roanoke va
amy wilde, 334 bayshore pkwy, mountain view ca
sal carpenter, 73 6th street, boston ma
[[email protected] home]# awk ‘{print toupper($0)}‘ list
JOHN DAGGETT, 341 KING ROAD, PLYMOUTH MA
ALICE FORD, 22 EAST BROADWAY, RICHMOND VA
ORVILLE THOMAS, 11345 OAK BRIDGE ROAD, TULSA OK
TERRY KALKAS, 402 LANS ROAD, BEAVER FALLS PA
ERIC ADAMS, 20 POST ROAD, SUDBURY MA
HUBERT SIMS, 328A BROOK ROAD, ROANOKE VA
AMY WILDE, 334 BAYSHORE PKWY, MOUNTAIN VIEW CA
SAL CARPENTER, 73 6TH STREET, BOSTON MA
範例12:awk命令提供一個統計字符串長度的函數length()。
[[email protected] home]# echo "abcde" | awk ‘{print length($0)}‘
5
[[email protected] home]# echo "abcde" | awk -F ‘‘ ‘{print NF}‘
5
[[email protected] home]# echo "abcde" | wc -L
5
[[email protected] home]# cat test.sh
#!/bin/bash
var="abcde"
echo ${#var}
[[email protected] home]# ./test.sh
5
第10章:awk進階操作