在類 UNIX 操作系統,特別是 Linux 系統中,命令行提供了一整套強大的文本處理工具,這些工具對于文件差異對比、內容篩選、文本排序以及源代碼管理尤為重要。今天,我們將結合真實示例,深入介紹并實戰演示 comm、uniq、diff、patch 和 sort 五大命令的用法,深入探討工具背后的原理和工具間的協作機制,幫助讀者更高效地處理文本數據。
一、基礎概念與環境準備
在 Linux 中,文本處理工具的設計哲學是“做一件事并做好”,這些工具通常專注于單一功能,但通過管道(|
)和重定向(>
、<
)等機制組合使用,可以實現復雜的數據處理任務。以下是我們將使用的測試環境和文件準備步驟。
1.1 創建測試環境
為了便于演示,我們首先在用戶主目錄下創建一個實驗目錄并生成幾個測試文件,分別代表不同的類 UNIX 系統類型:
mkdir -p ~/textcompare && cd ~/textcompare
創建四個測試文件:gnu
、linux
、bsd
和 unix
,內容如下:
cat > gnu << EOF
Arch Hurd
Debian GNU/Hurd
Debian GNU/kFreeBSD
Debian GNU/Linux
Guix System
EOFcat > linux << EOF
Debian GNU/Linux
Gentoo
Android
Alpine Linux
OpenWRT
Ubuntu
EOFcat > bsd << EOF
FreeBSD
OpenBSD
GhostBSD
Debian GNU/kFreeBSD
NetBSD
DragonFly BSD
EOFcat > unix << EOF
macOS
AIX
Solaris
OpenBSD
FreeBSD
EOF
這些文件模擬了不同系統發行版的清單,我們將使用它們來演示 comm
、uniq
、diff
、patch
和 sort
的功能。
1.2 工具概覽
以下是本文將介紹的五個工具的核心功能概覽:
工具 | 主要功能 | 典型應用場景 |
---|---|---|
comm | 比較兩個已排序文件的交集和差異 | 查找文件內容的共有和獨有部分 |
uniq | 去重、統計重復行 | 日志分析、數據清洗 |
sort | 按指定規則排序文本行 | 數據預處理、字段排序 |
diff | 比較文件差異并生成補丁 | 版本控制、配置文件對比 |
patch | 應用補丁修改文件內容 | 軟件更新、配置合并 |
這些工具的組合使用可以覆蓋從簡單文本處理到復雜版本控制的多種場景。
二、comm:高效比較兩個有序文件的交集與差異
2.1 用法與原理
comm
命令用于比較兩個已排序的文本文件,輸出結果分為三列:
- 第一列:僅在第一個文件中出現的行
- 第二列:僅在第二個文件中出現的行
- 第三列:兩個文件共有的行
comm
的基本語法如下:
comm [OPTION] FILE1 FILE2
注意:comm
要求輸入文件已排序,因此通常需要配合 sort
命令使用。如果文件未排序,結果可能不準確。
常用選項包括:
-1
:隱藏第一列(僅 FILE1 的行)-2
:隱藏第二列(僅 FILE2 的行)-3
:隱藏第三列(共有的行)--check-order
:檢查輸入文件是否已排序--nocheck-order
:忽略排序檢查
2.2 示例演示
假設我們要比較 gnu
和 linux
文件的內容。首先確保文件已排序,這里使用進程替換將命令執行結果當作一個文件交給 comm:
comm <(sort gnu) <(sort linux)
輸出結果(假設以制表符分隔):
Alpine LinuxAndroid
Arch Hurd
Debian GNU/HurdDebian GNU/Linux
Debian GNU/kFreeBSDGentoo
Guix SystemOpenWRTUbuntu
- 第一列:僅在
gnu
中出現的內容 - 第二列:僅在
linux
中出現的內容 - 第三列:共有的內容
如果只想查看 gnu
獨有的內容:
comm -23 <(sort gnu) <(sort linux)
只查看交集:
comm -12 <(sort gnu) <(sort linux)
三、uniq:去重與重復行統計
3.1 用法與原理
uniq
命令用于處理文本中的重復行,通常與 sort
配合使用,因為它只檢測連續的重復行。基本語法為:
uniq [OPTION] [INPUT [OUTPUT]]
常用選項:
-c
:在每行前顯示重復次數-d
:只輸出重復的行-u
:只輸出不重復的行-i
:忽略大小寫-f N
:忽略每行前 N 個字段-s N
:忽略每行前 N 個字符
3.2 示例演示
假設我們將所有測試文件合并為 all.txt
:
cat gnu linux bsd unix > all.txt
統計每種系統出現的次數:
sort all.txt | uniq -c
輸出:
1 AIX1 Alpine Linux1 Android1 Arch Hurd1 Debian GNU/Hurd2 Debian GNU/Linux2 Debian GNU/kFreeBSD1 DragonFly BSD2 FreeBSD1 Gentoo1 GhostBSD1 Guix System1 NetBSD2 OpenBSD1 OpenWRT1 Solaris1 Ubuntu1 macOS
其中,Debian GNU/kFreeBSD
出現了兩次(在 gnu
和 bsd
中)。
只顯示重復的行:
sort all.txt | uniq -d
輸出:
Debian GNU/kFreeBSD
FreeBSD
OpenBSD
四、sort:文本排序的多面手
4.1 用法與原理
sort
命令用于對文本行進行排序,支持多種排序規則。基本語法為:
sort [OPTIONS] [FILE...]
常用選項:
-n
:按數字排序-r
:倒序排序-k
:指定排序字段(例如-k2
表示按第二列排序)-t
:指定字段分隔符-f
:忽略大小寫-u
:去重(等同于sort | uniq
)-R
:隨機排序
4.2 示例演示
對 all.txt
按字典序排序:
sort all.txt
按行長度排序(結合 awk
預處理):
awk '{print length($0), $0}' all.txt | sort -n | awk '{$1=""; print $0}'
輸出:
AIXmacOSGentooNetBSDUbuntuAndroidFreeBSDFreeBSDOpenBSDOpenBSDOpenWRTSolarisGhostBSDArch HurdGuix SystemAlpine LinuxDragonFly BSDDebian GNU/HurdDebian GNU/LinuxDebian GNU/LinuxDebian GNU/kFreeBSDDebian GNU/kFreeBSD
字段排序:對 /etc/passwd
按 UID(第 3 字段)排序:
sort -t: -k3,3n /etc/passwd
五、diff:文件差異分析的利器
5.1 用法與原理
diff
命令用于比較兩個文件的差異,輸出差異的行或生成補丁文件。基本語法為:
diff [OPTION] FILE1 FILE2
常用選項:
-u
:生成統一格式(unified format)的補丁-c
:生成上下文格式的補丁-y
:并排顯示差異(side-by-side)-r
:遞歸比較目錄--brief
:僅報告是否有差異
5.2 示例演示
要比較 gnu
和 linux
文件并生成統一格式的補丁文件,我們可以使用以下命令:
diff -u gnu linux > gnu-linux.patch
輸出補丁文件:
--- gnu 2025-06-06 17:25:23.430342856 +0800
+++ linux 2025-06-06 17:25:23.434342856 +0800
@@ -1,5 +1,6 @@
-Arch Hurd
-Debian GNU/Hurd
-Debian GNU/kFreeBSDDebian GNU/Linux
-Guix System
+Gentoo
+Android
+Alpine Linux
+OpenWRT
+Ubuntu
解讀:
- 行首以
-
開頭的行(如Arch Hurd
、Debian GNU/Hurd
、Debian GNU/kFreeBSD
、Guix System
)表示僅存在于gnu
文件中的內容。 - 行首以
+
開頭的行(如Gentoo
、Android
、Alpine Linux
、OpenWRT
、Ubuntu
)表示僅存在于linux
文件中的內容。 - 無標記的行(如
Debian GNU/Linux
)表示兩個文件共有的內容。 @@ -1,5 +1,6 @@
表示差異的行范圍:gnu
文件從第1行開始有5行,linux
文件從第1行開始有6行。
為了更直觀地比較兩個文件的內容,可以使用并排(side-by-side)格式:
diff -y gnu linux
輸出如下:
Arch Hurd <
Debian GNU/Hurd <
Debian GNU/kFreeBSD <
Debian GNU/Linux Debian GNU/Linux
Guix System | Gentoo> Android> Alpine Linux > OpenWRT > Ubuntu
解讀:
- 左側列顯示
gnu
文件的內容,右側列顯示linux
文件的內容。 - 共有的行(如
Debian GNU/Linux
)對齊顯示。 - 獨有的行以
<
(僅在gnu
中)或>
(僅在linux
中)標記。 - 空行表示對方文件中沒有對應內容。
雖然命令行中的并排輸出便于快速查看,但對于大型文件或復雜差異,終端顯示可能顯得不夠直觀。此時,可以借助圖形化工具進一步增強體驗。推薦使用圖形化工具如 Meld 或 Vimdiff:
meld gnu linux
或者 Vimdiff,它是Vim 編輯器的內置差異模式:
vim -d gnu linux
六、patch:應用差異更新文件
6.1 用法與原理
patch
命令用于將 diff
生成的補丁應用到目標文件,實現內容的更新。基本語法為:
patch [OPTION] < PATCH_FILE
常用選項:
-pN
:剝離 N 級路徑前綴-R
:反向應用補丁-i
:指定補丁文件
6.2 示例演示
將 gnu-linux.patch
應用到 gnu
文件:
cp gnu gnu.bak
patch gnu < gnu-linux.patch
檢查 gnu
文件內容,應與 linux
文件一致。
反向恢復:
patch -R gnu < gnu-linux.patch
patch 操作,即打補丁操作對于軟件的開發是十分有用的,像對軟件的源代碼進行打補丁其實用的就是patch
這個命令,感興趣的話可以自行深入學習。
七、工具間的協同工作
7.1 典型組合
這些工具的真正威力在于組合使用。以下是一些典型場景:
- 查找獨有和共有內容:
comm -12 <(sort gnu) <(sort linux) > common.txt
comm -23 <(sort gnu) <(sort linux) > gnu-only.txt
comm -13 <(sort gnu) <(sort linux) > linux-only.txt
- 日志分析與去重:
cat access.log | sort | uniq -c | sort -nr > error-stats.txt
統計日志中重復錯誤并按次數倒序排列。
- 版本差異管理:
diff -u old.conf new.conf > config.patch
patch -p0 < config.patch
生成并應用配置文件補丁。
7.2 復雜實戰:分析多文件交集與差異
假設我們需要找出所有文件中獨有和共有的系統類型:
cat gnu linux bsd unix | sort | uniq -c > systems.txt
篩選出現多次的系統:
awk '$1 > 1' systems.txt
輸出:
2 Debian GNU/kFreeBSD
進一步比較 bsd
和 unix
的差異:
diff -y bsd unix
輸出:
FreeBSD | macOS
OpenBSD | AIX
GhostBSD | Solaris
Debian GNU/kFreeBSD <
7.3 工具間的依賴關系
sort
是基礎:comm
和uniq
依賴已排序的輸入。diff
和patch
成對使用:diff
生成補丁,patch
應用補丁。- 管道連接:通過
|
將工具串聯,形成數據處理流水線。