1. 程式人生 > >第10章:awk進階操作

第10章:awk進階操作

模式 rpe .sh 定義變量 能夠 all 模式匹配 mon ble

10章:awk進階操作

     在第4章:查找與替換簡單的講解了awk的使用,本章介紹詳細講解awk的使用。awk是一個強大的文本分析工具,簡單的說awk就是把文件逐行的讀入,

  以空格為默認分隔符將每行切片,切開的部分再進行各種分析處理。在shell腳本中文本處理功能awk功能其強大。

7.1awk命令形式

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.2awk內置變量

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

範例10awk命令嵌套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

範例11awk命令提供兩個函數用於完成字符串大小寫轉換,函數為小寫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

範例12awk命令提供一個統計字符串長度的函數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進階操作