跳至內容

AWK

出自Taiwan Tongues 台語維基
於 2025年8月22日 (五) 14:54 由 TaiwanTonguesApiRobot留言 | 貢獻 所做的修訂 (從 JSON 檔案批量匯入)

(差異) ←上個修訂 | 已批准修訂 (差異) | 最新修訂 (差異) | 下個修訂→ (差異)

AWK是一種優良的文字處理工具,Linux 佮 Unix 環境內底這馬有的功能上強大的資料處理 ia̋n-jín 之一。這種編程佮資料操作語言(其名稱得自伊的創始人阿爾佛雷德 ・ 艾侯、那個得 ・ 溫伯格佮布萊恩 ・ 柯林漢姓的首个字母)的上大功能決定一个人所擁有的智識。AWK 提供真正是真強大的功能:會當進行正規表示式的匹配,太陽入去、流控制、數學運算子、行程控制語句甚至於內建的變數佮函式。伊具備了一个完整的語言所應具有的差不多所有真濟精美的特性。實際上 AWK 的確實有家己的語言:AWK 程式設計語言,三个建立者已經共正式定義做「太濟掃描和處理語言」。 伊允准伊的建立簡短的程式,遮的程式讀輸入檔案、為資料排序、處理資料、對輸入執行計算以及生成報表,閣有無數其他的功能。gawk 是 AWK 的 GNU 版本。

上簡單的講,AWK 是一種用佇咧處理文字的程式語言工具。AWK 佇真濟方面類似講 Unix shell 程式語言,就算講 AWK 具有完全屬於其本身的語法。伊的設計思想來源於著 SNOBOL 四、sed、Marc Rochkind 設計的有效性語言嘛、語言工具 yacc 和 lex,當然猶閣自 C 語言內底取一寡優秀的思想。佇上早創造 AWK 時,其目的是用文字來處理,並且這種語言的基礎是,只要佇輸入資料當中攏有模式匹配,就執行系列指令。該實用工具掃描檔案中的每一途,走揣佮命令列內底所予定內容相匹配的模式。你若發現匹配的內容,則進行後一个編程程序細。你若揣無匹配的內容,愛繼續處理後一逝。

AWK 程式結構

> AWK 是一種處理文字檔案的語言。伊就共檔案做記錄序列處理。佇一般情形下,檔 àn-nāi 容的逐行攏是一个記錄。每行內容攏會予人分割做一系列的域,所以,咱會當認為一行的第一个詞為第一个域,第二个詞為第二个,以此類推。AWK 程式是由一寡處理特定模式的語句構成的。AWK 一改會當讀輸入去。對逐个輸入行,AWK 直譯器會判斷伊是毋是符合程式當中出現的各個模式,而且執行符合的模式所對應的動作。 > >

AWK 程式是由一系列的模式--動作對組成的,寫做

` ` ` _ pattern _ { _ action _ } ` ` `

其中 ` pattern ` 表示 AWK 佇資料當中走揣的內容,而且 ` action ` 是咧揣著匹配的內容的時陣所執行的一系列命令。輸入行予人分做一寡記錄:記錄預設由換行符分割,因此輸入會照行進行分割。程式使用予定的條件一个個的測試每一條記錄,執行測試通過的條件所對應的 ` action `。` pattern ` 和 ` action ` 攏會當省起來無寫。沒有 ` pattern ` 注文設匹配全部的記錄;而無 ` action ` 是列印原始的記錄。簡單的 AWK 表達式以外,` pattern ` 會當是 ` BEGIN ` 抑是 ` END `;這兩種條件對應的 ` action ` 分別是讀所有的記錄進前佮了後。同時,如 ` pattern 一 , pattern 二 ` 的條件表示符合條件 ` pattern 一 ` 和 ` pattern 二 ` 的記錄佮其中之間的部份。

除了一般的,C 語言風格的算術佮邏輯運算子外,AWK 允准運算子 _ ~ _,用來試正規表示式敢會當佮一字串匹配。做糖仔,無咧 _ ~ _ 運算子的正規表示式會予人用來對當前記錄進行測試,相當於是 ` / regexp / ~ $ 零 `。

AWK 命令

AWK 命令就為前文例中以 _ action _ 指代的語句。AWK 命令會使包括函式呼叫,共伊變數量量,計算,佮 / 抑是各項的組合。標準 AWK 提供真濟內建函式的;其部份實這馬可能提供閣較濟的內建函式。同時,AWK 的部份實現支援動態連結庫,予其實會當支援閣較濟的函式。 利便起見,來講古可能省略仔大括號(_ { } _)。

_ print _ 命令

_ print _ 命令用佇輸出文字。其實輸出的文字總是以 " 輸出記錄分隔符 "(Output record separator , ORS)分割的,其預設值為換行符仔。該命令的上簡形式為:

print

會輸出當前記錄的內容。佇咧 AWK 中,記錄會去予人分割去「域」,𪜶會當予人分別顯示抑是使用:

print $ 一

顯示當前記錄的第一个域

print $ 一 , $ 三

顯示當前記錄的頭一和第三个域,並且預定義的輸出域分隔符(Output field separator , OFS)分隔,其預設值做一个空格符雖然域的符號 ( _ $ X _ ) 可能類似某一寡語言內底的變數(比如講 PHP 和 perl), 猶毋過佇 AWK 中,𪜶的指代的是當前記錄的域。另外咧,_ $ 零 _ 是講規个記錄。事實上,命令 ` print ` 和 ` print $ 零 ` 的效果是相仝的。_ print _ 命令嘛會當顯示變數、計算、函式呼叫的結果:

` ` ` print 三 + 二 print foobar ( 三 ) print foobar ( variable ) print sin ( 三孵二 ) ` ` `

其輸出會當重新導向到位 File :

` ` ` print " expression " > " file name " ` ` `

抑是重新導向到管道:

` ` ` print " expression " | " command " ` ` `

內建變數

AWK 內建變數包括域變數,比如講 $ 一 , $ 二 , $ 三,以及 $ 零。遮的變數予出記錄中域的內容。 內建變數也包括一寡仔其他的變數:

  • NR:已經輸入記錄的條數。
  • NF:當前記錄中域的個數。記錄中上尾仔一个域會使 ` $ NF ` 的方式參照。
  • FILENAME:做前輸入檔案的檔名。
  • FS:「 域分隔符」,用佇咧將輸入記錄分割成域。其預設值為「空白字元」,即空格和制表符。FS 會當替換做其他的字元,對而且改變域分隔符。
  • RS:當前的「記錄分隔符」。 按算狀態之下,輸入的逐行攏予人做為一个記錄,因此預設記錄分隔符是換行符。
  • OFS:「 輸出域分隔符」,即分隔 ` print ` 命令的參數的符號。其預設的空格。
  • ORS:「 輸出記錄分隔符」,即每一个 ` print ` 命令之間的符號。其預設值為換行符仔。
  • OFMT:「 輸出數字格式」(Format for numeric output), 其預設值為 " % . 六 g "。

變數佮語法

變數名會當是語言關鍵字外的,干焦包含大細寫拉丁字母,數字佮底線(「 \ _」)的任意字。啊若運算子「+-\ * /」是分別代表加,減,乘,除。簡單的欲兩个變數(抑是字串常數)濫做伙,則會共二者接做一字串。若二者間至少有一个是常數,中央會使無加空格;若二者做變數,中央著愛包括空格。字串常數是以雙引號(「 "」)分隔的。語句並無需要分號結尾。另外咧,注釋是以「#」一開頭。

使用者定義函式

函式是以佮 C 語言類似的方式定義的,以關鍵字 ` function ` 一開頭,後壁佮函式名稱,參數列和函式體。

` ` `

  1. 示例函縛

function add _ three ( number ) { return number + 三 } ` ` `

頂懸的函式會當按呢呼叫:

` ` ` print add _ three ( 三十六 ) # 影響出三十九 ` ` `

函式會當有其私有變數。其私有變數會當寫佇參數列了後,因為遮的值得會咧呼叫函式的時陣予人無注意。通常會當佇參數列中參數佮私有變數之間加入一寡空格,用區別「真的」參數佮私有變數。 函式聲明中,函式名佮括號間會當有任意空格,但是咧呼叫時二者著愛趕緊。

看起來程式

Hello World

AWK 的 _ hello world _ 程式為:

` ` ` BEGIN { print " Hello , world ! " } ` ` `

注意此處無需要寫出 ` exit ` 語句,因為唯一的模式是 ` BEGIN `。

輸出長度大於八十的行

輸出長度大於八十字元的行。注意模式的預設行為是輸出當前行。

` ` ` length ( $ 零 ) > 八十 ` ` `

輸出單詞計數

對輸入中的單詞來進行計數,然後輸出行數,單詞數佮字元數(類似 wc)。

` ` ` { w +=NF c +=length + 一 } END { print NR , w , c } ` ` `

因為無提供模式,輸入的全部攏會當做匹配該模式,所以對逐行攏會執行預定操作。注意 ` w +=NF ` 的含義等仝款 ` w=w + NF `。

計算最後一个單詞的佮

` ` ` { s +=$ NF } END { print s + 零 } ` ` `

` s ` 是數值 ` $ NF ` 的忝加,` $ NF ` 是逐條記錄中的上尾仔一个域,` NF `(無咧 $)是當前行中域的數量。譬如講一个域數是四的行中 ` $ NF ` 相當於是 ` $ 四 `。事實上,` $ ` 是一个具有上高優先級的一元運算子。(若一行無域,則有 ` NF ` 為零,而且 ` $ NF ` 相當於是 ` $ 零 `,是整行,佇這个情形下,若空字捾,干焦空白符,所以其數值為零。)

檔案結束的時陣,` END ` 模式來得著匹配,所以會使輸出 ` s `。毋過,佇咧無輸入行的情況下,` s ` 會無值,對爾致使無輸出。所以,嘿其加零會使用 AWK 佇這種情形下著其實會當值,對若得著一个數值。這種方法是將字串強制轉化做數值的慣用法(反之,佮空字串連接也是會數值強制轉換做字串的方法,比如講 ` s " " `)。 按呢處理了後,若程式輸入做空縫案,會用得著「零」作為輸出,毋是一个空行。

匹配輸入行的範圍

` ` ` $ yes Wikipedia | awk'NR  % 四==一 , NR  % 四==三 { printf " % 六 d % s \ n " , NR , $ 零 }'| sed 七 q 一 Wikipedia 二 Wikipedia 三 Wikipedia 五 Wikipedia 六 Wikipedia 七 Wikipedia 九 Wikipedia $ ` ` `

yes 命令重複輸入其參數(預設是輸出「y」)。 佇遮,咱予彼个命令輸出「Wikipedia」。 動作塊是輸出帶行號的內容。` printf ` 函式會當類比標準 C 中的 ` printf ` 函式,其效果佮前述的 ` print ` 函式類似。符合模式的行是按呢來產生的:` NR ` 是記錄的編號,也就是講 AWK 當咧處理行的行號(自一開始)。「%」是取數運算子。所以,` NR  % 四==一 ` 嘿第一,五,九等行為真。類似的,` NR  % 四==三 ` 嘿三,七,十一等行為真。範圍模式佇其第一部份匹配(譬如講對第一行)進前為假,並且佇第二部份匹配(比如講第三行)進前為真。然後,閣佇第二改匹配頂懸其實第一部份(比如講第五行)前為假。` sed ` 命令是用佇咧截取其前七行輸出,防止 ` yes ` 命令一直執行落去。若是 ` head ` 若命令會當用,這途令的效果佮 ` head-n 七 ` 相仝。 若範圍模式的第一部份永遠為真,譬如講設定做「一」,會當用來使用範圍對輸入的上開始開始。類似的,你若第二部份總是替假,比如講「零」,則該範圍的結束就為輸入的結束。 命令

` ` ` / ^--cut here--$ / , 零 ` ` `

會輸出對符合正規表示式「^--cut here--$」開始的輸入行,從從只包括「--cut here--」 的行開始,一直到輸入的結束。

計算詞頻

使用關聯陣列計算詞頻:

` ` ` BEGIN { FS=" [^ a-zA-Z] + " } { for ( i=一 ; i <=NF ; + + i ) words [tolower ( $ i )] + + } END { for ( i in words ) print i , words [i] } ` ` `

` BEGIN ` 塊設定域分隔符為任意非字母字元。值得注意的是,分隔符毋但會使是字串,嘛會當是正規表示式的。然後,程式對逐个輸入行執行仝款的操作。在此,對每一个域,咱忝加其小寫的形式出現的次數。最後咧,佇咧 ` END ` 塊著,阮去輸出單詞佮其他的次數。代碼

` ` ` for ( i in words ) ` ` `

建立一个遍歷關聯陣列中元素的迴圈,其中,` i ` 會去予人設做對應的鍵。這點佮多數語言無仝,而佮 Objective-C 二鋪空中的 ` for . . . in ` 語法相𫝛。這款的語法允准以簡單的方式遍歷陣列,對遐輸出遮的單詞。另外咧,` tolower ` 函式是 One True awk(見下文)的附加函式。

對命令匹配模式

這个程式會當用較濟種無仝形式來出現。頭一个使用 Bourne shell 指令碼來完成大部份的工課。這嘛是上短的一个方法:

` ` ` $ cat grepinawk pattern=$ 一 shift awk'/'$ pattern'/ { print FILENAME " : " $ 零 }'$ * $ ` ` `

awk 命令著的 ` $ pattern ` 並無做引號所保護。佇遮,模式會當檢查輸入行(` $ 零 `)其實敢有啥物款的配合。` FILENAME ` 變數則包含著當前的檔名。awk 無顯式的字串連接運算子;佮 BASH 相仝,只需要簡單的將字串並列即可。` $ 零 ` 是會輸出原始的輸入行。 嘛有另外的方法來完成仝款的任務。下底的指令碼直接佇 awk 中存取環境變數。

` ` ` $ cat grepinawk pattern=$ 一 shift awk'$ 零 ~ ENVIRON [" pattern "] { print FILENAME " : " $ 零 }'$ * $ ` ` `

這个指令碼用到陣列 ` ENVIRON `,一个 One True awk 中引入的量。其實有這種類似佮 POSIX 標準中的 getenv ( 三 ) 函式。這个指令碼先建立著一个號做 ` pattern ` 的環境變數,其值為指令碼的第一个參數,然後予 awk 賰的參數所代表的檔 àn-nāi 走揣該模式。` ~ ` 是因為檢查其兩个運算元是毋是匹配的運算子;其逆則為 ` ! ~ `。注意正規表示式也屬於普通的字串,會當儲存佇咧變數當中。 下跤的方法則採用佇命令列對變數有價值的方法,就佇咧 awk 的參數中寫入一个變數的值:

` ` ` $ cat grepinawk pattern=$ 一 shift awk'$ 零 ~ pattern { print FILENAME " : " $ 零 }'" pattern=$ pattern " $ * $ ` ` `

最後咧,這種方法是純 awk 的,不需 shell 的幫助,嘛無需要知影傷濟關於著 awk 指令碼實現的細節(佇咧命令列對變數數量的方法可能佮 awk 的實現相關); 但是這種方法的指令碼小可仔長:

` ` ` BEGIN { pattern=ARGV [一] for ( i=一 ; i < ARGC ; i + + ) # 去除第一个li̋n-jín ARGV [i]=ARGV [i + 一] ARGC—if ( ARGC==一 ) { # 模式是唯一li̋n-jín,因為按呢允准允准 ARGC=二 ARGV [一]="-" } } $ 零 ~ pattern { print FILENAME " : " $ 零 } ` ` `

` BEGIN ` 塊的作用毋但是提出第一个參數,嘛防止第一个參數佇咧 ` BEGIN ` 塊煞了後直接予人解說做輸入檔案。` ARGC `,輸入參數量永遠是無小於一的,因為乎 ` ARGV [零] ` 是執行指令碼的號令名,通常是 ` " awk " `。另外咧,` ARGV [ARGC] ` 永遠是空字串。著其中的 ` if ` 塊,伊的表明若無指定輸入檔案,awk 會直接讀取標準輸入流(` stdin `)。 嘛即

` ` ` awk'prog' ` ` `

嘛會當做工課,因為程式內底已經共 ` ARGC ` 二搭為著;若該值為一,著 awk 會認為講無檔案愛讀取直接登出。同時,若是需要對標準輸入讀資料,需要將檔名顯式的指定做 `-`。

自包括的 AWK 指令碼

佮真濟其他的程式語言相𫝛,會當利用「shebang」語法構建自包含的 awk 指令碼。 比如講,一个叫做 ` hello . awk `,會當輸出「Hello , world !」的 UNIX 命令會當通過建立內容如下,號做 ` hello . awk ` 的檔案來完成:

` ` `

  1. ! / usr / bin / awk-f

BEGIN { print " Hello , world ! " } ` ` `

`-f ` 參數共 awk 共這个檔案做為 awk 的程式檔案,隨後會當執行該程式。

參見

  • sed
  • Unix shell
  • Perl
  • PowerShell


參考文獻

外部連結

  • gawk 頭頁
  • aaa-the Amazing Awk Assembler by Henry Spencer
  • Awk 教學