這篇文章將為大家詳細(xì)講解有關(guān)linux中如何使用awk完成更多結(jié)構(gòu)化的復(fù)雜任務(wù),小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
創(chuàng)新互聯(lián)專注骨干網(wǎng)絡(luò)服務(wù)器租用十年,服務(wù)更有保障!服務(wù)器租用,重慶服務(wù)器托管 成都服務(wù)器租用,成都服務(wù)器托管,骨干網(wǎng)絡(luò)帶寬,享受低延遲,高速訪問。靈活、實現(xiàn)低成本的共享或公網(wǎng)數(shù)據(jù)中心高速帶寬的專屬高性能服務(wù)器。
awk
腳本是由 {}
(大括號)包圍的功能塊組成,其中有兩個特殊的功能塊,BEGIN
和 END
,它們在處理第一行輸入流之前和最后一行處理之后執(zhí)行。在這兩者之間,塊的格式為:
模式 { 動作語句 }
當(dāng)輸入緩沖區(qū)中的行與模式匹配時,每個塊都會執(zhí)行。如果沒有包含模式,則函數(shù)塊在輸入流的每一行都會執(zhí)行。
另外,以下語法可以用于在 awk
中定義可以從任何塊中調(diào)用的函數(shù)。
function 函數(shù)名(參數(shù)列表) { 語句 }
這種模式匹配塊和函數(shù)的組合允許開發(fā)者結(jié)構(gòu)化的 awk
程序,以便重用和提高可讀性。
awk
每次從輸入文件或流中一行一行地讀取文本,并使用字段分隔符將其解析成若干字段。在 awk
的術(shù)語中,當(dāng)前的緩沖區(qū)是一個記錄。有一些特殊的變量會影響 awk
讀取和處理文件的方式:
FS
(
)。默認(rèn)情況下,這是任何空格字符(空格或制表符)。
RS
(
)。默認(rèn)情況下是一個新行(n
)。
NF
(
)。當(dāng) awk
解析一行時,這個變量被設(shè)置為被解析出字段數(shù)。
$0:
當(dāng)前記錄。
$1
、$2
、$3
等:當(dāng)前記錄的第一、第二、第三等字段。
NR
(
)。迄今已被 awk
腳本解析的記錄數(shù)。
影響 awk
行為的變量還有很多,但知道這些已經(jīng)足夠開始了。
對于一個如此強大的工具來說,有趣的是,awk
的大部分用法都是基本的單行腳本。也許最常見的 awk
程序是打印 CSV 文件、日志文件等輸入行中的選定字段。例如,下面的單行腳本從 /etc/passwd
中打印出一個用戶名列表:
awk -F":" '{print $1 }' /etc/passwd
如上所述,$1
是當(dāng)前記錄中的第一個字段。-F
選項將 FS
變量設(shè)置為字符 :
。
字段分隔符也可以在 BEGIN
函數(shù)塊中設(shè)置:
awk 'BEGIN { FS=":" } {print $1 }' /etc/passwd
在下面的例子中,每一個 shell 不是 /sbin/nologin
的用戶都可以通過在該塊前面加上匹配模式來打印出來:
awk 'BEGIN { FS=":" } ! /\/sbin\/nologin/ {print $1 }' /etc/passwd
現(xiàn)在你已經(jīng)掌握了一些基礎(chǔ)知識,嘗試用一個更具有結(jié)構(gòu)化的例子來深入了解 awk
:創(chuàng)建郵件合并。
郵件合并使用兩個文件,其中一個文件(在本例中稱為 email_template.txt
)包含了你要發(fā)送的電子郵件的模板:
From: Program committeeTo: {firstname} {lastname} <{email}>Subject: Your presentation proposal Dear {firstname}, Thank you for your presentation proposal: {title} We are pleased to inform you that your proposal has been successful! Wewill contact you shortly with further information about the eventschedule. Thank you,The Program Committee
而另一個則是一個 CSV 文件(名為 proposals.csv
),里面有你要發(fā)送郵件的人:
firstname,lastname,email,titleHarry,Potter,hpotter@hogwarts.edu,"Defeating your nemesis in 3 easy steps"Jack,Reacher,reacher@covert.mil,"Hand-to-hand combat for beginners"Mickey,Mouse,mmouse@disney.com,"Surviving public speaking with a squeaky voice"Santa,Claus,sclaus@northpole.org,"Efficient list-making"
你要讀取 CSV 文件,替換第一個文件中的相關(guān)字段(跳過第一行),然后把結(jié)果寫到一個叫 acceptanceN.txt
的文件中,每解析一行就遞增文件名中的 N
。
把 awk
程序?qū)懺谝粋€叫 mail_merge.awk
的文件中。在 awk
腳本中的語句用 ;
分隔。第一個任務(wù)是設(shè)置字段分隔符變量和其他幾個腳本需要的變量。你還需要讀取并丟棄 CSV 中的第一行,否則會創(chuàng)建一個以 Dear firstname
開頭的文件。要做到這一點,請使用特殊函數(shù) getline
,并在讀取后將記錄計數(shù)器重置為 0。
BEGIN { FS=","; template="email_template.txt"; output="acceptance"; getline; NR=0;}
主要功能非常簡單:每處理一行,就為各種字段設(shè)置一個變量 —— firstname
、lastname
、email
和 title
。模板文件被逐行讀取,并使用函數(shù) sub
將任何出現(xiàn)的特殊字符序列替換為相關(guān)變量的值。然后將該行以及所做的任何替換輸出到輸出文件中。
由于每行都要處理模板文件和不同的輸出文件,所以在處理下一條記錄之前,需要清理和關(guān)閉這些文件的文件句柄。
{ # 從輸入文件中讀取關(guān)聯(lián)字段 firstname=$1; lastname=$2; email=$3; title=$4; # 設(shè)置輸出文件名 outfile=(output NR ".txt"); # 從模板中讀取一行,替換特定字段, # 并打印結(jié)果到輸出文件。 while ( (getline ln < template) > 0 ) { sub(/{firstname}/,firstname,ln); sub(/{lastname}/,lastname,ln); sub(/{email}/,email,ln); sub(/{title}/,title,ln); print(ln) > outfile; } # 關(guān)閉模板和輸出文件,繼續(xù)下一條記錄 close(outfile); close(template);}
你已經(jīng)完成了! 在命令行上運行該腳本:
awk -f mail_merge.awk proposals.csv
或
awk -f mail_merge.awk < proposals.csv
你會在當(dāng)前目錄下發(fā)現(xiàn)生成的文本文件。
awk
中最強大的功能之一是關(guān)聯(lián)數(shù)組,在大多數(shù)編程語言中,數(shù)組條目通常由數(shù)字索引,但在 awk
中,數(shù)組由一個鍵字符串進行引用。你可以從上一節(jié)的文件 proposals.txt
中存儲一個條目。例如,在一個單一的關(guān)聯(lián)數(shù)組中,像這樣:
proposer["firstname"]=$1; proposer["lastname"]=$2; proposer["email"]=$3; proposer["title"]=$4;
這使得文本處理變得非常容易。一個使用了這個概念的簡單的程序就是詞頻計數(shù)器。你可以解析一個文件,在每一行中分解出單詞(忽略標(biāo)點符號),對行中的每個單詞進行遞增計數(shù)器,然后輸出文本中出現(xiàn)的前 20 個單詞。
首先,在一個名為 wordcount.awk
的文件中,將字段分隔符設(shè)置為包含空格和標(biāo)點符號的正則表達式:
BEGIN { # ignore 1 or more consecutive occurrences of the characters # in the character group below FS="[ .,:;()<>{}@!\"'\t]+";}
接下來,主循環(huán)函數(shù)將遍歷每個字段,忽略任何空字段(如果行末有標(biāo)點符號,則會出現(xiàn)這種情況),并遞增行中單詞數(shù):
{ for (i = 1; i <= NF; i++) { if ($i != "") { words[$i]++; } }}
最后,處理完文本后,使用 END
函數(shù)打印數(shù)組的內(nèi)容,然后利用 awk
的能力,將輸出的內(nèi)容用管道輸入 shell 命令,進行數(shù)字排序,并打印出 20 個最常出現(xiàn)的單詞。
END { sort_head = "sort -k2 -nr | head -n 20"; for (word in words) { printf "%s\t%d\n", word, words[word] | sort_head; } close (sort_head);}
在這篇文章的早期草稿上運行這個腳本,會產(chǎn)生這樣的輸出:
[dneary@dhcp-49-32.bos.redhat.com]$ awk -f wordcount.awk < awk_article.txtthe 79awk 41a 39and 33of 32in 27to 26is 25line 23for 23will 22file 21we 16We 15with 12which 12by 12this 11output 11function 11
關(guān)于“l(fā)inux中如何使用awk完成更多結(jié)構(gòu)化的復(fù)雜任務(wù)”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。