溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

linux中如何使用awk完成更多結(jié)構(gòu)化的復(fù)雜任務(wù)

發(fā)布時(shí)間:2021-10-28 17:55:11 來源:億速云 閱讀:149 作者:小新 欄目:系統(tǒng)運(yùn)維

這篇文章將為大家詳細(xì)講解有關(guān)linux中如何使用awk完成更多結(jié)構(gòu)化的復(fù)雜任務(wù),小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。


awk 的程序結(jié)構(gòu)

awk 腳本是由 {}(大括號(hào))包圍的功能塊組成,其中有兩個(gè)特殊的功能塊,BEGIN 和 END,它們?cè)谔幚淼谝恍休斎肓髦昂妥詈笠恍刑幚碇髨?zhí)行。在這兩者之間,塊的格式為:

模式 { 動(dòng)作語句 }

當(dāng)輸入緩沖區(qū)中的行與模式匹配時(shí),每個(gè)塊都會(huì)執(zhí)行。如果沒有包含模式,則函數(shù)塊在輸入流的每一行都會(huì)執(zhí)行。

另外,以下語法可以用于在 awk 中定義可以從任何塊中調(diào)用的函數(shù)。

function 函數(shù)名(參數(shù)列表) { 語句 }

這種模式匹配塊和函數(shù)的組合允許開發(fā)者結(jié)構(gòu)化的 awk 程序,以便重用和提高可讀性。

awk 如何處理文本流

awk 每次從輸入文件或流中一行一行地讀取文本,并使用字段分隔符將其解析成若干字段。在 awk 的術(shù)語中,當(dāng)前的緩沖區(qū)是一個(gè)記錄。有一些特殊的變量會(huì)影響 awk 讀取和處理文件的方式:

  • FS

    字段分隔符field separator

    )。默認(rèn)情況下,這是任何空格字符(空格或制表符)。

  • RS

    記錄分隔符record separator

    )。默認(rèn)情況下是一個(gè)新行(n)。

  • NF

    字段數(shù)number of fields

    )。當(dāng) awk 解析一行時(shí),這個(gè)變量被設(shè)置為被解析出字段數(shù)。

  • $0: 當(dāng)前記錄。

  • $1、$2、$3 等:當(dāng)前記錄的第一、第二、第三等字段。

  • NR

    記錄數(shù)number of records

    )。迄今已被 awk 腳本解析的記錄數(shù)。

影響 awk 行為的變量還有很多,但知道這些已經(jīng)足夠開始了。

單行 awk 腳本

對(duì)于一個(gè)如此強(qiáng)大的工具來說,有趣的是,awk 的大部分用法都是基本的單行腳本。也許最常見的 awk 程序是打印 CSV 文件、日志文件等輸入行中的選定字段。例如,下面的單行腳本從 /etc/passwd 中打印出一個(gè)用戶名列表:

awk -F":" '{print $1 }' /etc/passwd

如上所述,$1 是當(dāng)前記錄中的第一個(gè)字段。-F 選項(xiàng)將 FS 變量設(shè)置為字符 :。

字段分隔符也可以在 BEGIN 函數(shù)塊中設(shè)置:

awk 'BEGIN { FS=":" } {print $1 }' /etc/passwd

在下面的例子中,每一個(gè) shell 不是 /sbin/nologin 的用戶都可以通過在該塊前面加上匹配模式來打印出來:

awk 'BEGIN { FS=":" } ! /\/sbin\/nologin/ {print $1 }' /etc/passwd

awk 進(jìn)階:郵件合并

現(xiàn)在你已經(jīng)掌握了一些基礎(chǔ)知識(shí),嘗試用一個(gè)更具有結(jié)構(gòu)化的例子來深入了解 awk:創(chuàng)建郵件合并。

郵件合并使用兩個(gè)文件,其中一個(gè)文件(在本例中稱為 email_template.txt)包含了你要發(fā)送的電子郵件的模板:

From: Program committee <pc@event.org>To: {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

而另一個(gè)則是一個(gè) 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 文件,替換第一個(gè)文件中的相關(guān)字段(跳過第一行),然后把結(jié)果寫到一個(gè)叫 acceptanceN.txt 的文件中,每解析一行就遞增文件名中的 N。

把 awk 程序?qū)懺谝粋€(gè)叫 mail_merge.awk 的文件中。在 awk 腳本中的語句用 ; 分隔。第一個(gè)任務(wù)是設(shè)置字段分隔符變量和其他幾個(gè)腳本需要的變量。你還需要讀取并丟棄 CSV 中的第一行,否則會(huì)創(chuàng)建一個(gè)以 Dear firstname 開頭的文件。要做到這一點(diǎn),請(qǐng)使用特殊函數(shù) getline,并在讀取后將記錄計(jì)數(shù)器重置為 0。

BEGIN {  FS=",";  template="email_template.txt";  output="acceptance";  getline;  NR=0;}

主要功能非常簡單:每處理一行,就為各種字段設(shè)置一個(gè)變量 &mdash;&mdash; firstname、lastnameemail 和 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 &lt; template) &gt; 0 )        {                sub(/{firstname}/,firstname,ln);                sub(/{lastname}/,lastname,ln);                sub(/{email}/,email,ln);                sub(/{title}/,title,ln);                print(ln) &gt; outfile;        }         # 關(guān)閉模板和輸出文件,繼續(xù)下一條記錄        close(outfile);        close(template);}

你已經(jīng)完成了! 在命令行上運(yùn)行該腳本:

awk -f mail_merge.awk proposals.csv

awk -f mail_merge.awk < proposals.csv

你會(huì)在當(dāng)前目錄下發(fā)現(xiàn)生成的文本文件。

awk 進(jìn)階:字頻計(jì)數(shù)

awk 中最強(qiáng)大的功能之一是關(guān)聯(lián)數(shù)組,在大多數(shù)編程語言中,數(shù)組條目通常由數(shù)字索引,但在 awk 中,數(shù)組由一個(gè)鍵字符串進(jìn)行引用。你可以從上一節(jié)的文件 proposals.txt 中存儲(chǔ)一個(gè)條目。例如,在一個(gè)單一的關(guān)聯(lián)數(shù)組中,像這樣:

        proposer["firstname"]=$1;        proposer["lastname"]=$2;        proposer["email"]=$3;        proposer["title"]=$4;

這使得文本處理變得非常容易。一個(gè)使用了這個(gè)概念的簡單的程序就是詞頻計(jì)數(shù)器。你可以解析一個(gè)文件,在每一行中分解出單詞(忽略標(biāo)點(diǎn)符號(hào)),對(duì)行中的每個(gè)單詞進(jìn)行遞增計(jì)數(shù)器,然后輸出文本中出現(xiàn)的前 20 個(gè)單詞。

首先,在一個(gè)名為 wordcount.awk 的文件中,將字段分隔符設(shè)置為包含空格和標(biāo)點(diǎn)符號(hào)的正則表達(dá)式:

BEGIN {        # ignore 1 or more consecutive occurrences of the characters        # in the character group below        FS="[ .,:;()<>{}@!\"'\t]+";}

接下來,主循環(huán)函數(shù)將遍歷每個(gè)字段,忽略任何空字段(如果行末有標(biāo)點(diǎn)符號(hào),則會(huì)出現(xiàn)這種情況),并遞增行中單詞數(shù):

{        for (i = 1; i &lt;= NF; i++) {                if ($i != "") {                        words[$i]++;                }        }}

最后,處理完文本后,使用 END 函數(shù)打印數(shù)組的內(nèi)容,然后利用 awk 的能力,將輸出的內(nèi)容用管道輸入 shell 命令,進(jìn)行數(shù)字排序,并打印出 20 個(gè)最常出現(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);}

在這篇文章的早期草稿上運(yùn)行這個(gè)腳本,會(huì)產(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)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI