Linux awk 資料處理與分析神器

awk(名稱來自三位開發者 Aho, Weinberger, Kernighan)是 Linux 上最強大的文字分析工具。 它把檔案視為一張「試算表」,一行是一筆記錄 (Record),一欄是一個欄位 (Field)。 最常用來做:擷取特定欄位(例如只看 Log 的 IP 欄位)。

基本語法

awk '{print $欄位編號}' 檔案
  • $0:代表「整行」
  • $1:代表「第 1 欄」
  • $2:代表「第 2 欄」
  • $NF:代表「最後一欄」 (Number of Fields)

預設使用 空白Tab 作為分隔符號。

常用範例

1. 顯示檔案的第一欄

# 列出系統所有使用者帳號 (格式是 root:x:0:0...)
# 這裡用 -F 指定用冒號 : 分隔
awk -F ':' '{print $1}' /etc/passwd

2. 也是 grep:條件過濾

awk 也可以用來搜尋。

# 只顯示 UID 大於 1000 的使用者
awk -F ':' '$3 >= 1000 {print $1, $3}' /etc/passwd

# 搜尋包含 "error" 的行 (類似 grep error)
awk '/error/ {print $0}' /var/log/syslog

3. 統計與計算

假設有一個薪資檔 salary.txt (姓名 薪水):

Alice 3000
Bob 4500
Charlie 2800

我們可以輕鬆算總和:

awk '{sum += $2} END {print "Total:", sum}' salary.txt

內建變數

  • NR (Number of Records):目前處理到第幾行。
  • FS (Field Separator):分隔符號 (預設空白)。
  • OFS (Output Field Separator):輸出的分隔符號 (預設空白)。

加上行號顯示

awk '{print NR, $0}' /etc/passwd


## 進階格式化輸出 (`printf`)
`print` 會自動換行,但如果有時候你想印出漂亮的表格,就要用 `printf` (跟 C 語言很像)。

```bash
# %-10s: 字串靠左佔 10 格
# %5d:   整數靠右佔 5 格
awk -F ':' '{printf "User: %-15s UID: %5d\n", $1, $3}' /etc/passwd

BEGIN 與 END 區塊

這是 awk 的程式架構:

  1. BEGIN: 讀取檔案前執行一次 (通常用來初始化變數或印標題)。
  2. Main: 每一行都會執行一次。
  3. END: 讀完所有檔案後執行一次 (通常用來印總結)。
awk 'BEGIN {print "Name\tSalary"} 
     {print $1, "\t", $2} 
     END {print "--------------\nDone"}' salary.txt

邏輯控制 (If-Else)

awk 其實是一門完整的程式語言,支援 if, for, while

# 如果 UID >= 1000 印 "User",否則印 "System"
awk -F ':' '{
    if ($3 >= 1000) 
        print $1, "is User"
    else 
        print $1, "is System"
}' /etc/passwd

內建字串函數

  • length($0): 計算長度
  • toupper($1) / tolower($1): 轉大小寫
  • substr($1, 1, 3): 取子字串
# 印出長度超過 20 的行
awk 'length($0) > 20' /var/log/syslog

實戰:Nginx Log 分析

假設 Log 格式如下: 192.168.1.1 - - [12/Dec/2023...] "GET /index.html..." 200 1024

統計每個 IP 的存取次數 (最重要的指令!)

這招必學!用 Array 來計數。

# $1 是 IP
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -nr | head
  • count[$1]++: 建立一個叫做 count 的陣列,Key 是 IP ($1),每次遇到就 +1。
  • END { ... }: 讀完後跑迴圈,印出結果。
  • sort -nr: 照數字大小反向排序 (最多的在上面)。