摘要:Robbins 認爲 AWK缺少名稱空間是它沒有成爲被廣泛使用的編程語言的主要原因之一,而且gawk 5.0中的此功能可能有助於解決該問題。Robbins在他的2018年論文中主張將AWK(特別是gawk)用作“系統編程語言”,在這種情況下,其含義是用於編寫較大的工具和程序的語言。

【CSDN編者按】AWK是一種文本處理語言,距今已經歷了40多年的發展。它支持POSIX標準,有幾種符合標準的實現,在2020年居然仍然有着大量擁躉,無論是用於簡單的文本處理任務還是用於處理“大數據”。

恰逢最近GNU Awk 5.1發佈,我們正好給了我們一個理由,通覽AWK前景,GNU Awk已經達到的成果,以及如今AWK用在哪裏了。
這門語言在1977年誕生於貝爾實驗室。其名稱來自其作者的名字縮寫:Alfred Aho,Peter Weinberger和Brian Kernighan。AWK是核心的Unix工具,旨在做一件事:過濾和轉換文本行。它通常用於解析日誌文件中的字段,轉換其他工具的輸出以及計算單詞和字段的出現次數。
Aho 簡要總結了 AWK的功能:

AWK從輸入中按行讀取。每行數據都會和程序中的每個模式進行匹配,併爲每個匹配的模式執行關聯的動作。
AWK程序通常是直接從命令行執行的單行代碼。例如,要從某個假定的Web服務器日誌中計算GET請求的平均響應時間,可以輸入如下代碼:
$ awk '/GET/ {total += $6; n++} END {print total/n}' server.log 0.0186667
這意味着:對於與正則表達式/GET/匹配的所有行 ,將其響應時間(第六字段,即$6)加起來並統計行數;最後,打印出響應時間的算術平均值。

各種AWK版本
當前使用的AWK有三個主要版本,並且它們都符合POSIX標準(至少對於絕大多數用例而言,足夠接近)。第一個是經典awk,它是Aho,Weinberger和Kernighan在他們的《 AWK編程語言》一書中描述的AWK版本。有時稱爲“新AWK”(nawk)或“一個真正的AWK”,現在託管在GitHub上。這是許多基於BSD的系統(包括macOS)上預先安裝的版本(儘管macOS隨附的版本已過時,需要升級)。
第二個是GNU Awk(gawk),它是迄今爲止功能最強大,維護最活躍的版本。Gawk通常預先安裝在Linux系統上,並且通常是默認的awk。使用Homebrew可以很容易地在macOS上安裝,Gawk還提供Windows二進制文件。自1994年以來,Arnold Robbins一直是gawk的主要維護者,並繼續推廣該語言(他還爲經典的awk版本做出了許多修復)。Gawk具有awk或POSIX標準中未提供的許多功能,包括新函數,聯網功能,C擴展API,事件探查器和調試器以及最近的名稱空間。
第三個通用版本是mawk,由Michael Brennan編寫。它是Ubuntu和Debian Linux上的默認awk,並且仍然是AWK的最快版本,具有字節碼編譯器和更節省內存的值表示形式。(從4.0開始,Gawk還使用了字節碼編譯器,因此它現在已經接近mawk的速度。)
如果你想將AWK用於單行和基本文本處理,則上述任何方法都是不錯的選擇。如果你打算將其用於較大的腳本或程序,Gawk的功能使其成爲明智的選擇。
AWK的其他幾種實現也具有不同的成熟度和維護級別。值得注意的有這些:嵌入式Linux環境中使用的尺寸優化的BusyBox版本,支持運行時訪問Java語言的Java版以及我自己用Go編寫的GoAWK(與POSIX兼容的版本)。三個主要的AWK和BusyBox版本都用C編寫。

自4.0以來的變化
自LWN 涵蓋 gawk 4.0發行以來,已經過去了將近10年。你可能會說“自2011年以來發生了很多變化”,但事實是AWK世界中的進展相對緩慢。我將在此介紹自4.0以來的重大功能,更多詳細信息,你可以閱讀完整的4.x和5.x 更改日誌。Gawk 5.1.0已於一個月前(4月14日)發佈。
面向用戶的最大功能是在5.0中引入名稱空間。大多數現代語言都有一些名稱空間的概念,這可以使大型項目和庫的發佈更加容易,而不會造成名稱衝突。Gawk 5.0以向後兼容的方式添加名稱空間,從而允許開發人員創建庫,例如此玩具數學庫:
要引用庫中的變量或函數,請使用 namespaceC :: name語法,類似於C ++:
$ gawk -f area.awk -e 'BEGIN {print area :: pi,area :: circle(10)}' 3.14159 314.159
Robbins 認爲 AWK缺少名稱空間是它沒有成爲被廣泛使用的編程語言的主要原因之一,而且gawk 5.0中的此功能可能有助於解決該問題。Robbins認爲阻礙AWK的另一個主要問題是缺少良好的C擴展接口。Gawk的動態擴展界面在4.1中進行了徹底改進。它現在已具備定義良好的擴展API,並允許包裝現有的C和C ++庫,以便可以從AWK輕鬆調用它們。
以下代碼片段出自用戶手冊中C代碼包裝器的示例,它的功能是用文件名和stat系統調用的值填充AWK數組(字符串作爲鍵的哈希表):
/*填寫數組*/ array_set(array,“name”,make_const_string(name,strlen(name),&tmp)); array_set_numeric(array,“dev”,sbuf-> st_dev); array_set_numeric(array,“ino”,sbuf-> st_ino); array_set_numeric(array,“mode”,sbuf-> st_mode);
4.2版本中的另一個更改(並在5.0中繼續)是對源代碼漂亮打印機的全面檢查。Gawk的漂亮打印機可以將其用作標準化的AWK代碼格式化程序,類似於Go的go fmt工具和Python的 Black格式化程序。例如,要漂亮地打印上面提到的 area.awk文件,使用如下命令:
$ gawk --pretty-print -f area.awk
@namespace "area" BEGIN { pi = 3.14159 # namespaced "constant" } function circle(radius) { return (pi * radius * radius)
你可能會質疑工具的選擇:爲什麼“ BEGIN { ”沒有像函數一樣在“{ ”前加入換行符?(事實證明AWK語法不允許這樣做。)爲什麼在函數前有兩個空行並在return表達式前後加上括號?但是至少它是一致的,並且可能有助於避免代碼風格的爭論。
Gawk允許數量有限的運行時類型檢查,並通過在4.2中添加typeof函數進行擴展 。根據輸入類型,typeof返回一個字符串常量,例如“ string ”,“ number ”或“ array ”。這些功能對於遞歸遍歷嵌套數組的每個項目非常重要(這是POSIX AWK無法做到的)。
在4.2版中,gawk還使用@/foo/語法將正則表達式常量作爲一等數據類型 。以前,你無法將正則表達式常量存儲在變量中。使用typeof(@/foo/)判斷其數據類型將返回字符串“ regexp ”。gawk 4.2在Linux系統的性能方面進行了重大改進,它將盡量使用fwrite_unlocked來提升性能。由於gawk是單線程的,因此可以使用無鎖的stdio函數,從而使原始輸出速度提高了7-18%(使用原始輸出的命令是這樣的gawk'{print}')。
《GNU Awk用戶指南》是一份詳盡的參考資料,並在4.1版和5.x版中進行了實質性更新,包括新示例,摘要部分和練習,以及一些主要的副本編輯。
最後(也是最不重要的一點),我發現4.0版本中一個有趣的細微變化是對sub和 gsub中反斜槓的還原處理。Robbins寫道:
sub和gsub中反斜槓的默認處理已恢復爲3.1。我認爲破壞兼容性是很愚蠢的,即使是爲了符合標準。
該sub 和gsub函數是核心的正則表達式替換功能,甚至一個涉及複雜處理反斜槓的小“修復”就能破壞已有的代碼:
當4.0.0版發佈時,gawk維護者將POSIX規則設置爲默認規則,打破了十多年的向後兼容性。不用說,這是個壞主意,從4.0.1版開始,gawk恢復了其歷史行爲,並且僅在給出--posix時才遵循POSIX規則。
Robbins進行最初的更新時可能判斷不足,但是很明顯他很重視向後兼容性。尤其是對於像gawk這樣的流行工具,有時繼續打破規範比改變某些東西的工作方式更好。

AWK是否仍然有意義?
AWK是否仍然有用這個問題,就像在問空氣是否有用一樣:你可能看不到它,但周圍無處不在。許多Linux管理員和DevOps工程師使用它來轉換數據或通過日誌文件診斷問題。幾乎所有基於Unix的計算機上都安裝了AWK版本。除了臨時使用外,許多大型開源項目還在其構建或文檔工具中使用AWK。僅舉幾個例子:Linux內核在x86工具中使用它來檢查 和重新格式化 objdump文件,Neovim使用它來生成文檔,而FFmpeg使用它來進行構建和測試。
即使人們不再想看到AWK,AWK構建腳本也很難被殺死:2018年,LWN 寫了一篇文章,是關於GCC貢獻者想要用Python替換AWK腳本來生成其選項解析代碼。這個建議在當時有一些支持,但顯然沒有人主動要求做實際的移植,現在AWK腳本依然存在。
Robbins在他的2018年論文中主張將AWK(特別是gawk)用作“系統編程語言”,在這種情況下,其含義是用於編寫較大的工具和程序的語言。他概述了他認爲尚未流行的原因,但Kernighan“ 並非100%確信 ”缺乏擴展機制是AWK不被大型程序廣泛使用的主要原因。他建議,這可能是由於缺乏對訪問系統調用等內容的內置支持。但是,這些都沒有阻止幾個人開發更大的工具:Robbins自己編寫的TexiWeb Jr.識字編程工具(1300行AWK),Werner Stoop的d.awk工具用於從源碼中備註的MarkDown生成文檔, Translate Shell是一個6000行AWK工具,可爲基於雲的翻譯API提供相當強大的命令行界面。
過去幾年中,有幾位開發人員寫過關於在其“大數據”工具包中使用AWK的信息,它比重型分佈式計算系統(如Spark和Hadoop)簡單得多(有時更快)。Nick Strayer 撰寫了 有關使用AWK和R解析多個內核中25 TB數據的文章。其他大數據示例包括Adam Drake 寫的標題頗爲誘人的文章:“命令行工具可以比Hadoop集羣快235倍”,以及Brendan O'Connor的“ 不要使用MAWK,AWK是最快,最優雅的大數據處理語言”。
總而言之,在臨時文本修改,構建工具,“系統編程”和大數據處理之間(更不用說文本模式的第一人稱射擊遊戲),AWK似乎在2020年還活得很好。
原文鏈接:
https://lwn.net/SubscriberLink/820829/5bf9bf8bb9d6f2bf/
本文爲CSDN翻譯文章,轉載請註明出處。
相關文章