管道(|)是 Linux 哲學「做一件事,做好它」的極致體現——將上一個命令的標準輸出直接作為下一個命令的標準輸入,構建強大的文字處理流水線。本文深度講解 grep、cut、sort、uniq 四大核心管道工具的進階用法與組合技巧。
grep:模式匹配利器
核心選項速查
| 選項 | 長選項 | 功能 |
-E | --extended-regexp | 使用擴展正則表達式(ERE) |
-P | --perl-regexp | 使用 Perl 相容正則(PCRE),功能最強 |
-F | --fixed-strings | 固定字串匹配(不解析正則,速度最快) |
-i | --ignore-case | 忽略大小寫 |
-v | --invert-match | 反向匹配(顯示不匹配行) |
-n | --line-number | 顯示行號 |
-c | --count | 只輸出匹配行計數 |
-o | --only-matching | 只輸出匹配部分(每行一個) |
-A n | --after-context | 顯示匹配行後 n 行 |
-B n | --before-context | 顯示匹配行前 n 行 |
-C n | --context | 顯示匹配行前後各 n 行 |
-r | --recursive | 遞歸搜尋目錄 |
-l | --files-with-matches | 只輸出包含匹配的檔案名 |
-L | --files-without-match | 只輸出不包含匹配的檔案名 |
實戰範例
# 檢查是否安裝 httpd
rpm -qa | grep httpd
# 在檔案中搜尋字串(兩種等價寫法)
grep 'Hello' hi.txt
cat hi.txt | grep 'Hello'
# 遞歸搜尋包含 "TODO" 的程式碼檔案,顯示行號
grep -rn "TODO" /path/to/project --include="*.py" --include="*.js"
# 只輸出匹配的 IP 位址
grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' access.log
# 排除註釋行與空行
grep -vE '^#|^$' config.conf
# 顯示匹配行及前後各 2 行
grep -C 2 "ERROR" app.log
cut:欄位提取專家
核心選項
| 選項 | 長選項 | 功能 |
-d | --delimiter | 指定分隔符(預設 Tab) |
-f | --fields | 指定欄位編號(1-based) |
-c | --characters | 按字元位置切分 |
-b | --bytes | 按位元組位置切分 |
-s | --only-delimited | 不輸出不含分隔符的行 |
--output-delimiter | | 指定輸出分隔符 |
欄位範圍語法
N 第 N 欄位
N- 第 N 欄位到行尾
N-M 第 N 到第 M 欄位
-M 第 1 到第 M 欄位
- 所有欄位
實戰範例
# 提取 /etc/passwd 所有用戶名(第 1 欄位,分隔符 :)
cut -d ':' -f 1 /etc/passwd
# root
# daemon
# ...
# 提取第 1、3、6 欄位(用戶名、UID、家目錄)
cut -d ':' -f 1,3,6 /etc/passwd
# 提取第 3 欄位到行尾
cut -d ':' -f 3- /etc/passwd
# 固定寬度切分(如 lastb 輸出的 IP 位置)
lastb | cut -c 23-38 | sort | uniq -c | sort -nr
# 61 220.225.70.251
# 11 119.161.208.37
# 9 213.229.124.66
# ...
# 指定輸出分隔符為 |
cut -d ':' -f 1,3,6 --output-delimiter='|' /etc/passwd
sort:排序大師
核心選項
| 選項 | 長選項 | 功能 |
-n | --numeric-sort | 數值排序(非字典序) |
-r | --reverse | 逆序 |
-u | --unique | 去重(配合 -c 檢查) |
-k | --key | 指定排序鍵:k start[,end] |
-t | --field-separator | 指定分隔符 |
-h | --human-numeric-sort | 人類可讀數值排序(1K, 2M, 1G) |
-V | --version-sort | 版本號排序(1.2.10 > 1.2.9) |
-s | --stable | 穩定排序(保持相等元素原序) |
-S | --buffer-size | 指定緩衝區大小(如 50% 或 1G) |
關鍵語法:-k 精準控制
-k 2 # 從第 2 欄位到行尾
-k 2,2 # 僅第 2 欄位
-k 2,4 # 第 2 到第 4 欄位
-k 2.3,2.5 # 第 2 欄位第 3 字元到第 5 字元
-k 2nr # 第 2 欄位數值逆序(n+r 組合)
實戰範例
# /etc/passwd 按 UID(第 3 欄位)數值排序
cat /etc/passwd | sort -t ':' -k 3n
# 目錄大小人類可讀排序
du -h | sort -hr
# 版本號排序
echo -e "1.2.10\n1.2.9\n1.10.0" | sort -V
# 1.2.9
# 1.2.10
# 1.10.0
# 複合排序:先按第 1 欄位字典序,再按第 2 欄位數值逆序
sort -k1,1 -k2,2nr data.txt
uniq:去重統計專家
核心選項
| 選項 | 長選項 | 功能 |
-c | --count | 每行前加上計數 |
-d | --repeated | 只顯示重複行 |
-u | --unique | 只顯示唯一行(不重複) |
-i | --ignore-case | 忽略大小寫比較 |
-f N | --skip-fields=N | 忽略前 N 個欄位比較 |
-s N | --skip-chars=N | 忽略前 N 個字元比較 |
-w N | --check-chars=N | 只比較前 N 個字元 |
核心原則:uniq 只能檢測相鄰重複行,必須先排序!
實戰範例
# 統計 /etc/passwd 各 GID(第 4 欄位)出現次數
cut -d ':' -f 4 /etc/passwd | sort -n | uniq -c
# 1 0
# 1 1
# 2 2
# ...
# 只顯示重複的 GID
cut -d ':' -f 4 /etc/passwd | sort -n | uniq -d
# 忽略大小寫去重
sort -f file.txt | uniq -i
# 忽略前 2 個欄位比較
uniq -f 2 sorted.txt
# 只比較前 10 個字元
uniq -w 10 sorted.txt
黃金組合招:四大工具聯動
場景 1:分析 SSH 失敗登入 IP
# 方案 1:lastb + cut + uniq
lastb | cut -c 23-38 | sort | uniq -c | sort -nr | head -10
# 方案 2:journalctl + grep + awk + sort + uniq(systemd 系統)
journalctl -u sshd | grep "Failed password" | \
awk '{for(i=1;i<=NF;i++) if($i=="from") print $(i+1)}' | \
sort | uniq -c | sort -nr | head -20
場景 2:分析 Nginx 訪問日誌 Top 10 IP
awk '{print $1}' /var/log/nginx/access.log | \
sort | uniq -c | sort -nr | head -10
場景 3:統計程式碼中 TODO/FIXME/XXX 標記
grep -rEn "(TODO|FIXME|XXX)" --include="*.py" --include="*.js" . | \
cut -d: -f1 | sort | uniq -c | sort -nr
場景 4:提取日誌中特定時間段的錯誤碼統計
# 假設日誌格式:[2024-01-15 10:30:45] ERROR code=500
grep "ERROR" app.log | \
grep "2024-01-15" | \
sed -E 's/.*code=([0-9]+).*/\1/' | \
sort | uniq -c | sort -nr
進階技巧:sort -u vs uniq
# sort -u 等同於 sort | uniq,但更高效(單進程完成去重)
sort -u file.txt
# uniq -c 可統計頻率,sort -u 無法統計
# 需要統計頻率時:sort | uniq -c | sort -nr
效能優化建議
- 大檔案排序:
sort -S 50% --parallel=$(nproc) bigfile.txt
- 避免不必要的
cat:grep pattern file 優於 cat file | grep pattern
- 固定字串匹配用
grep -F,避免正則解析開銷
- 大檔案去重:
sort -u -S 50% --parallel=$(nproc) bigfile.txt
- LC_ALL=C 可顯著提升排序/匹配速度:
LC_ALL=C sort bigfile.txt
總結
grep 篩選、cut 萃取、sort 排序、uniq 去重統計——這四大工具構成了 Linux 文字處理的「四大金剛」。熟練掌握它們的選項組合與管道串聯,能將複雜的資料分析任務拆解為優雅的一行命令。建議收藏本文速查表,在實戰中不斷練習組合拳,將管道藝術內化為直覺。