基礎

基礎

學習練習

簡介

基本概念

我們會將這門 語言 稱為AWK,並將解讀 AWK 程式的 執行檔 稱為**awk或gawk**。

模式與動作

一個 AWK 程式是由模式-動作配對組成。

pattern1 { action1 }
pattern2 { action2 }
...

模式可以是對輸入進行比對的正規表示式,也可以是任何能產生 true/false 值的運算式。

動作則是一個或多個 AWK 指令。外層的大括號是必要的。

如果模式的結果為 true,就會執行對應的動作。

記錄與欄位

AWK 會將輸入解析成一連串的記錄,再把每筆記錄分割成零個或多個欄位。

預設行為是:

  • 以換行作為「記錄分隔符」將輸入分割成記錄,因此每一 行 就是一筆記錄。
  • 以空白作為「欄位分隔符」將記錄分割成欄位,因此每一 詞 就是一個欄位。

模式與動作(續)

模式可以省略,此時動作會_對每一筆輸入記錄_執行。

動作也可以省略,此時預設動作是印出目前的記錄。

特殊模式

有兩種特殊模式經常會用到。

  • BEGIN會在讀取任何輸入之前執行對應的動作。
  • END會在讀取完所有輸入之後執行對應的動作。

欄位變數

你可以用$1、$2、$3等方式取用欄位。

目前的記錄是$0。

以下是一些其他常用的內建變數。

控制輸入解析的內建變數
  • RS是輸入記錄分隔符。如前所述,它的預設值是換行。
  • FS是輸入欄位分隔符。

這些變數通常會在BEGIN動作區塊中設定。

傳遞資訊的內建變數

這些變數會在程式執行期間由 AWK 自動設定。

  • NF會儲存目前記錄的欄位數量。
    • 想取得最後一個欄位的值,可以使用$NF。
  • NR會儲存目前的記錄編號。
    • 在處理多個輸入檔案時,NR會保存到目前為止已處理的記錄總數。
  • FNR會儲存目前輸入檔案中目前的記錄編號。
    • 為了說明 NR 與 FNR 的差異,以下是常見的 AWK 慣用寫法。
      NR == FNR {action}
      
      意思是「如果累計的記錄編號等於目前檔案的記錄編號」。這只有在_第一個輸入檔案_的記錄中才可能成立。

真值判斷

AWK 使用的真值概念和 C 相同。

  • 數字0為 false。
  • 其他任何數字都為 true。

由於 AWK 是文字處理語言,真值也會延伸到字串。

  • 空字串""為 false。
  • 任何非空字串都為 true。

註解

註解以#字元開頭,延伸到該行結尾。

範例

在類 Unix 系統中,/etc/passwd包含了使用者的資訊。每位使用者各佔一行,欄位之間以冒號分隔。

如要列出使用者名稱:

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

請注意,{print $1}動作沒有模式,因此會對每一筆記錄執行。

如果只想輸出使用 bash 作為登入 shell 的使用者,可以這樣寫:

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

說明

從前從前,有一座熱鬧繁華的城市,叫做 Cyberspace。 Cyberspace 是一座數位大都會,每天有數百萬名居民登入和登出。 為了追蹤所有這些使用者,Cyberspace 有一個特別的檔案,叫做 /etc/passwd。

/etc/passwd 檔案就像是這座城市的電話簿。 它列出了系統上每一個擁有帳號的使用者,以及每位使用者的一些重要資訊:

n 欄位
1 使用者名稱
2 密碼(「x」表示基於安全考量,實際密碼儲存在別的地方)
3 UID,唯一的使用者數值 ID
4 GID,唯一的群組數值 ID(通常與 UID 相同)
5 使用者資訊(通常是使用者的全名,但也可以包含其他資訊)
6 家目錄
7 登入 shell

這些欄位以冒號字元分隔。 以下是一個典型的條目:

glennj:x:1010:1010:Glenn Jackman:/home/glennj:/usr/local/bin/fish

這個檔案由一群系統管理員管理,他們負責建立新帳號、更新現有帳號,以及移除舊帳號。 系統管理員是 Cyberspace 的守門人,確保只有獲得授權的使用者才能存取系統。

有一天,團隊新聘了一位叫做 Alex 的系統管理員。 Alex 對接下這份工作感到很興奮,也很快就摸透了 /etc/passwd 檔案的來龍去脈。 他們學會了如何把新使用者加入系統、如何更新使用者資訊,以及如何移除舊使用者。

當 Alex 在處理 /etc/passwd 檔案時,他們注意到了一些奇怪的事。 有些使用者的家目錄很奇怪,或者不太尋常。 有些使用者的家目錄被設成 /dev/null,另一些使用者的家目錄則被設成根本不存在的奇怪路徑。

Alex 意識到這些使用者不是真人,而是駭客建立的假帳號。 駭客找到了利用系統漏洞的方法,並建立了這些假帳號來取得 Cyberspace 的存取權。

Alex 知道自己必須採取行動。 他們使用 awk 分析 /etc/passwd 檔案,並寫了一個指令碼來找出所有假帳號。 接著他們與團隊其他成員合作,移除這些帳號,並修補當初讓駭客得以建立這些帳號的漏洞。

多虧 Alex 使用了 awk,團隊才能找出並移除這些假帳號,讓 Cyberspace 成為對所有人來說更安全的地方。 系統管理員持續管理 /etc/passwd 檔案,讓它保持最新且安全,並確保只有獲得授權的使用者才能存取系統。

現在,輪到你來當像 Alex 一樣的系統管理員了。

Note

這裡還有一些解這道練習需要用到的 AWK 語法。

  • 布林運算子和其他語言很像:

    運算 範例
    AND expr1 && expr2
    OR expr1 || expr2
    NOT ! expr
  • 呼叫函式的語法也很熟悉:

    function greet(name) {
        print "Hello", name
    }
    BEGIN {
        greet("Mary")   # prints "Hello Mary"
    }
    

1. 列出使用者名稱

寫一個 awk 程式,印出 passwd 檔案中每一行以冒號分隔的第一個欄位。

2. 印出行號

寫一個 awk 指令,印出輸入檔案中每一筆紀錄的行號。 只印出行號,不要印出其他資訊。

3. 印出家目錄無效的紀錄。

在 Cyberspace 中,「有效」的家目錄會以/home或/root開頭。 印出輸入檔案中家目錄無效的紀錄。

4. 印出使用 bash 的有效使用者

印出家目錄有效且登入 shell 是bash的紀錄。


出處

ChatGPT 對話
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
AWK Exercism

準備好開始 基礎 了嗎?

註冊 Exercism,透過 3 個概念92 個練習 和真人引導來學習並精通 AWK,全部免費。