AWK用法全解

一、awk介紹

awk是Linux自帶的一個逐行掃描的文本處理工具,支持正則表達式、循環控制、條件判斷、格式化輸出。AWK自身帶有一些變量,可以在書寫腳本時調用。

二、基本語法格式

2.1、在shell中使用awk

awk [option] 代碼塊 文件名

  • option的選項及含義
選項 含義 使用演示 演示說明
-F 指定文件分隔符 awk -F "\n" 按\n做分隔符
-f 使用文件中的內容作爲命令輸入 awk -f  script.txt 使用script.txt文件中的內容作爲命令
-v 給變量賦值,支持多個v賦值 awk -v Num=$num -v Num1=$num1 把num的值給Num、num1的值給Num1
  • 代碼塊的說明:

條件判斷'{要執行的內容}'               注:條件判斷與“{”之間不帶空格,{}的兩側要使用單引號"'’"包圍。

條件判斷爲真則執行{}中的內容,條件判斷爲假則不執行{}中的內容。

例如:

awk -F "," NR==2'{print $1}' awktest.txt   

#將awktest.txt文件中的文本以",",如果行號爲2則打印第一列內容。

awk -F "," NR==10'{print "這是第"NR"行","第1列是:"$1,"第2列是:"$2}' awktest.txt

#打印多個列的字段、行號並於固定的字符串拼接

2.2、在腳本中使用awk代碼

有些腳本命令比較長,在shell中編輯比較麻煩,這時考慮將命令寫入腳本中方便保存和修改。

在腳本文件中,大致格式如下:

BEGIN{

語句一

語句二

}

表達式1 {要執行的內容}

表達式2 {要執行的內容}

END{

語句一

語句二

}

注意:{要執行的內容}中如果有多個語句要執行,使用","進行分割。在awk中,{}中的內容表示要執行的操作,賦值、判斷等操作可以放在{}之外。

  • 創建一個文件awkScript.txt
vi awkScript.txt

以下腳本文件中的FS、NR是awk的自帶變量,後面的內容中對此進行解釋。 

#awk的腳本文件
#開始部分,一般用於腳本執行前的初始化,比如設置每一列的標題、設置分割符等等。
BEGIN{
FS=","
print "第一列","第二列"
}

#這裏是主要執行的代碼塊
{print "這是第"NR"行"}
NR%2 {print NR,"這是偶數行"}

#END代碼塊。
END{
print "總計共有"NR"行"
print "腳本執行結束"
}
  • awk以腳本的方式執行這些文件
awk -f awkScript.txt awktest.txt

三、awk的內置變量

awk內置一些變量,這些變量可能會隨着文本讀取的進度發生變化,比如現在讀取到第幾行。我們可以調用這些內置變量。

變量名稱 說明 使用示例 示例說明
$number 記錄被分割後的第number列的字段,$表示整行文本。 {print $1,$3} 打印第1列和第3列字段
FS 字段分割符(可使用FlieSplit記憶) BEGIN{FS="\n"} 使用換行分割文本
NF 當前行中的字段數量 {print "當前行共有"NF"列"} 打印當前行的列數
NR 當前的行號(NnumberRow,從1開始) NR%2{print "這是偶數行"} 判斷是否是偶數行
RS 表示記錄分隔符,多行文本的情況下,RS字符將文本分割成幾個大塊(RowSplit)

BEGIN{

FS="\N"

RS=" "

}

對一個使用空行分割多個行的文本,RS表示的字符將文本分成多個段落,FS表示的字符將這些段落中的行分割成多個列。
OFS 表示輸出字段之間分隔符,將輸出的多個字段使用OFS拼接,缺省爲" "。(OutFileSpilt)

BEGIN{OFS=";"}

{print "字段1","字段2","字段3"}

輸出的字段1、字段2、字段3變成"字段1;字段2;字段3"
ORS 表示輸出行之間記錄分隔符,在兩個單獨行插入定義的字符串,缺省爲"\n"

BEGIN{

ORS="\n\n"

}

輸出的文本行之間有兩個空行

四、awk的正則表達式

awk的正則表達式和其他語言的正則表達式規則一致

字符

描述

.

可代替除一行之外的任何單個字符

*

可代替零個或多個在它前面出現的字符

[chars]

可代替chars中的任何一個字符,chars是一串字符序列。你可以用-符號來定義一個字符範圍。如果^是chars中的第一個字符,那麼將匹配沒有在chars中指定的字符

^

匹配一行的開頭

$

匹配一行的結尾

\

把\後面的字符照常輸出,通常用來轉義(不使用特殊含義)一個元字符

!~ 匹配到的內容取反,表示不匹配
  • 在{}包裹的語句塊之前使用正則表達式語法 

awk ‘/REG/{action}’        /REG/爲要匹配的內容,{action}爲匹配成功後要執行的動作。

#打印awktest.txt文件中包含2020年時間的行(使用"\"對/符號進行轉義)

awk -F "," '/2020\/[0-9]{1,2}\/[0-9]{1,2}/{print $0}' awktest.txt

匹配到的結果爲:

在{}代碼塊中使用正則表達式語法

awk -F "," '{if($0 ~ "2020/07/01"){print $0}else{print "none"}}' awktest.txt

五、awk控制流語句

5.1、條件語句

awkif語句類似於C語言的if語句

{ 
    if ( $1 == "foo" ) { 
        if ( $2 == "foo" ) { 
            print "uno" 
        } else { 
            print "one" 
        } 
    } else if ($1 == "bar" ) { 
        print "two" 
    } else { 
        print "three" 
    } 
} 

5.2、循環語句

  • do...while循環
{ 
    count=1 
    do { 
        print "I get printed at least once no matter what" 
    } while ( count != 1 ) 
} 
  • for循環
for ( x = 1; x <= 4; x++ ) { 
    print "iteration",x 
} 
  • break和continue語句

如同C語言一樣,awk提供了breakcontinue來控制awk的循環結構。break語句用於跳出最深層的循環,使循環立即終止,並繼續執行循環代碼塊後面的語句。continue語句使awk立即開始執行下一個循環迭代,而不執行代碼塊的其餘部分。

5.4、數組

awk中,數組下標通常從1開始,而不是0

myarray[1]="jim"
myarray[2]=456

 awk不需要連續的下標編號,例如,給myarray[1]賦值之後可以直接賦值myarrary[10]。

awk可以使用"in"操作來遍歷數組中的所有元素,但這種遍歷是無序的,無法保證按下標順序輸出。

for ( x in myarray ) { 
    print myarray[x] 
} 

 awk數組中還可以使用字符串下標,其實,不管你使用的下標是字符串還是數字,awk在幕後還將其認爲是字符串下標。

myarr["1"]="China" 
print myarr["1"] 
myarr["name"]="Mr. Whipple" 
print myarr["name"] 

六、awk的內置函數

awk並不像其他語言一樣,把字符串看作是字符數組。執行以下代碼:

mystring="How are you doing today?" 
print mystring[3] 

將會報錯: 

 awk: string.gawk:59: fatal: attempt to use scalar as array

爲了應對這種情況,awk內置了許多字符串函數。 

字符串函數 功能說明 使用示例 示例說明
length() 返回字符串的長度 print length(mystring)  打印mystring字符串的長度
index() 返回子字符串在另一個字符串中出現的位置 print index(mystring,"you")  返回子字符串“you”在另一個mystring中出現的位置,如果沒有找到該字符串則返回0
tolower() 返回字符串並且將所有字符轉換成小寫 print tolower(mystring)  把mystring所有的字母改成大寫
toupper() 返回字符串並且將所有字符轉換成大寫 print toupper(mystring)  把mystring所有的字母改成小寫
substr() 返回從字符串中選擇的子串 awk '{print substr($0,2,10)}' 打印字符串從第2位開始後面10個字符
match() 返回子字符串在另一個字符串中出現的位置。它與index()的區別在於它並不搜索子串,它搜索的是正則表達式。match()還將設置兩個變量,叫作RSTARTRLENGTHRSTART包含返回值(第一個匹配的位置),默認返回RESTART,RLENGTH指定它佔據的字符跨度(如果沒有找到匹配,則返回-1 print match($0,/2020\/07\/01/),RLENGTH 打印2020/07/01匹配到的起始位置和它的長度。
sub() 替換匹配的第一個字符序列,並返回整個字符串 sub(regexp,replstring,mystring)  replstring替換在mystring中匹配regexp的第一個字符序列,sub()替換第一個regexp匹配
gsub() 替換匹配的全部字符序列,並返回整個字符串 gsub(regexp,replstring,mystring)  replstring替換全部在mystring中匹配regexp的第一個字符序列
split() 分割字符串,並將各部分放到使用整數下標的數組中 num=split($0,var,",") {print var[1]} 將當前行的文本以","分割,放進var數組中,打印第一各元素。num爲接受分割後數組的長度。

七、awk的格式化輸出

然大多數情況下awkprint語句可以完成任務,但有時我們還需要更多。使用兩個函數printf()sprintf(),將能讓輸出錦上添花。printf()會將格式化字符串打印到stdout,而sprintf()則返回可以賦值給變量的格式化字符串。

x=1 
b="foo" 
printf("%s got a %d on the last test\n","Jim",83) 
myout=("%s-%d",b,x) 
print myout 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章