阿旺的 Linux 開竅手冊

 基礎篇    進階篇    補腦篇    指令索引  


HY-STAR's  Ads IWS's Ads


版權所有, 引用請註明出處

 進階篇

Advanced Chapter 3 : 過濾程式

A3.0 過濾器簡介
        grep 檔案中尋找字串
           egrep
           frgep
        cut 擷取欄位
        col 過濾控制字元
        tr 字元轉換
        sort 排序
        uniq 刪除相鄰重複的行




















正規表示法/過濾程式


A3.0 過濾器簡介
Unix/Linux 有一群很特別的工具軟體叫〝過濾器〞(filter),過濾器有些是不能由鍵盤直接輸入資料或單獨的使用,而是要經管線重定向來操作,過濾器基本以〝行〞(line)為單位來過濾文字、搜尋、修改、取代、插入、刪除或統計等來處理資料。

過濾器的操作基本上是輸出到 stdout 也就是螢幕,如要存檔要再重定向到檔案如 cat fileA | tr -s '\n' > fileB

過濾器工具軟體常用的有 grepcutcoltruniqsortsedawk 等,其中 sedawk 有自己專屬的腳本語言另成一格且相對複雜,故在 sedawk 章節獨立說明。

grep 檔案中尋找字串
grep 工具名稱來自 edex 行編輯器的搜尋命令 g/re/p (global/regular expression/print),所以顧名思義主要的功能是搜尋檔案中的資料。

指令 find 對找檔名威力無窮,但對搜尋檔案的內容卻無能為力,還好 Unix/Linux 有一法力無邊的工具 grep ,可配合正規表示法來搜尋檔案的內容。

基本的 grep 用法為 grep PATTERN FILE,即用正規表示法的 PATTERN(樣板)來匹配找出在檔案中符合的字串。

例如看帳號設定檔〝/etc/passwd〞的關鍵字串〝/home〞就可知系統設了那些帳號,可用 grep /home /etc/passwd 把有字串〝/home〞的行列出。

例:
$ grep home /etc/passwd ←列出檔案〝etc/passwd〞中字串〝home〞的行來看目前已建立的帳號
aaa:x:500:500::/home/aaa:/bin/bash
bbb:x:501:501::/home/bbb:/bin/bash
frank:x:502:502:Frank Wang:/home/frank:/bin/bash
phoebe:x:503:503::/home/phoebe:/bin/bash

但因 PATTERN(樣板)如用正規表示法可能很抽象,為了避免 PATTERN 被錯誤解讀,一般 PATEEN 的地方建議用引號「'」或「"」把其括起,故上例建議寫成 grep '/home' /etc/passwd

grep 本身並不難,難的是對正規表示法的熟練度。

例:
$ ls -F /etc | grep '/$' ←只列出〝/etc〞下的目錄但不包含檔案
a2ps/
acpi/
alsa/
alternatives/
audisp/
audit/
avahi/
blkid/
bluetooth/
以下略

grep 最有彈性的方法並不是直接操作檔案,而是經管線來操作(因可一直加條件),如下例:

$ ls -d /etc/* | grep [[:digit:]] | grep [[:upper:]] ←列出〝/etc〞目錄下用數字的和大寫字母的檔案
/etc/X11

在介紹正規表示法時有舉因 ls 只支援萬用字元很容易受不同的設定或環境而產生不同的輸出,可利用 grep 對正規表示法的支援來避開萬用字元的缺點,故同一功能用 ls + grep 改寫就不會環境影響。

例:
$ ls -d /etc/* | grep '[A-Z].*' ←列出〝/etc〞目錄下第一個字元為大寫的檔案或目錄
/etc/ConsoleKit
/etc/DIR_COLORS
/etc/group.OLD
/etc/Muttrc

有時只記得某檔案內容的某關鍵字,但忘了是那個檔案,此時用選項〝-r〞連同子目錄一起搜尋很方便。

例:
$ grep -r 'colou*r' /etc/gconf ←找出 /etc/gconf 內(含子目錄),檔案內容有〝color〞或〝colour〞檔案
/etc/gconf/gconf.xml.defaults/%gconf-tree-or.xml: <entry name="color_shading_ty
/etc/gconf/gconf.xml.defaults/%gconf-tree-or.xml: <entry name="secondary_color">
/etc/gconf/gconf.xml.defaults/%gconf-tree-or.xml: <entry name="primary_color">

grep 有二個選項很常用分別為 grep -F 為不用正規表示法解讀,而 grep -E 為用延伸正規表示法來匹配,使用時機和範例可參考 fgrepegrep

grep 可能的選項和用法如下:
語法:[STDIN] grep [-otpiton][--option] [FILE] or [STDOUT]
指令名稱/功能/命令使用者 選項 功能  
grep/
檔案中尋找字串/
Any
-a 搜尋二進制(binary)檔  
-A# 列出搜尋到的字串那行的內容和後 # 行內容(〝#〞為數字)  
-B# 列出搜尋到的字串那行的內容和前 # 行內容(〝#〞為數字)  
-C# 列出搜尋到的字串那行的內容和前後 # 行內容(〝#〞為數字)  
-c 顯示符合搜尋結果的列數  
-D[read][skip] 搜尋裝置檔或 Name PipeSocket 可接的項目有
〝read〞:把裝置檔當一般檔案處理
〝skip〞:不處理裝置檔
-d[read][skip][recurse] 搜尋目錄 此選項部分版本的 OS 或檔案系統可能不完整的支援或可能產生錯誤。
可接的項目有
〝read〞:把目錄當一般檔案處理
〝skip〞:不處理目錄
〝recurse〞:處理目錄和子目錄,同等選項〝-r〞
-e 指定樣板 主要用於處理以〝-〞開頭的檔案
(因以〝-〞開頭檔案和選項符號〝-〞相同沒用此選項會被誤判)
-E 強制用延伸正規表示法解讀搜尋的語法  
-f 指定樣板檔  
-F 用固定字串(即不用正規表示法解讀)搜尋  
-G 將指定樣板檔以基礎正規表示法解讀  
-h 搜尋多檔案時不列出檔案名稱 多檔案搜尋時才有區別
-H 列出符合字串的那一行的內容和檔案名稱(此為預設值)  
-i 忽略大小寫之差別  
-I 搜尋二進制檔如符合,不輸出〝Binary file XXX matches〞 此選項找二進檔檔時不顯示〝Binary file XXX〞以免干擾輸出畫面。

-l 只列出符合的檔案名稱 主要用於多檔案搜尋
-L 列出不符合的檔案名稱 主要用於多檔案搜尋
-n 列出符合字串的行號  
-q 不顯示輸出 主要用於 bash 檔當判斷時用
-r 連同子目錄一起搜尋  
-v 反相搜尋,即符合字串那一列反而不輸出  
-w 只匹配〝完整字〞(whole words)的字串 如完整字匹配〝apple〞而字串如為〝apples〞或〝applets〞等都不符合
-x 只匹配全列都符合的那一列  
--help 指令自帶說明  

其他常用的用法如下:

例:
$ grep -n 'google' re.txt ←列出字串所在的行數

另也可把要搜尋的 pattern 寫成樣板檔,改變搜尋的樣板檔就可改變搜尋的規則。

例:
$ cat MY_PATTERN ←例如有樣板檔〝MY_PATTERN〞內容如下:
TAIWAN
[Tt]aiwan
$ grep -f MY_PATTERN *.txt ←用樣板檔〝MY_PATTERN〞內的樣板搜尋所有副檔名為〝txt〞的檔案

此外如要搜尋的字串有〝-〞就要用 grep -e 來區別說〝-〞接的不是選項,而是要搜尋有字元〝-〞的字串。

例:
$ cat my_file ←例如有檔案〝my_file〞內容如下:
Introduction to Linux
Linux is a muti-user & muti-task OS

$ grep -e '-user' my_file ←搜尋檔案〝my_file〞中的字串'-user'
Linux is a muti-user & muti-task OS

grep -e 還有另一好用的地方,用於多重字串搜尋

例:
$ grep -ne 'mail' -ne 'news' /etc/passwd ←搜尋字串〝mail〞&〝news〞並列出行號
9:mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:news:x:9:13:news:/etc/news:
27:mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin

grep -q 不顯示輸出(安靜模式)常用於腳本語言作程式的判斷用。

例:
$ grep -q 'google' re.txt && cp re.txt re.txt~ ←如果檔案〝reg.txt〞有字串〝google〞,就備份此檔




^ back on top ^




cut 擷取欄位
cut 主要功能為擷取文字檔中的欄位,透過下面的實驗一步步說明

$ echo -e '12\t3\t456\t789'
12         3         456         789

上例用 tab (參考 ASCII 控制碼表示法)間隔共有四個欄位,如我想擷取第二和第四個欄位,用 cut 指令如下:

$ echo -e '12\t3\t456\t789' | cut -f 2,4
3         789

cut 預設的欄位間隔為 tab,而選項〝-f〞為要擷取輸出的欄位,擷取的欄位可如下表示。
-f n 擷取欄位 n
-f n,m,o,p 擷取欄位 n,m,o 和 p
-f n-m 擷取欄位從 n 到 m
-f n- 擷取欄位從 n 到最後
-f -n 擷取欄位從第一個 到第 n 個
-f n-m,o-p,q,r- 擷取欄位從 n 到 m, o 到 p,q 和 r 到最後

但並非所有資料的欄位間隔為都是 tab,例如 /etc/passwd 的欄位間隔為〝:〞,此時可用選項〝-d〞來指定欄位間隔的字元,如下例為指定欄位間隔的字元為〝:〞來列出所有的帳號。

例:
$ cat /etc/passwd | grep '/home' | cut -d":" -f1
aaa
bbb
patrick
cindy
danny

不只欄位,cut 也可用來擷取字元,如 cut -c 1-4 FILE 為擷取字元 1~4。

例:
$ echo '123456789' | cut -c 5- ←擷取字元從 5 到最後一個字元
56789

cut 選項和用法如下:
語法:[STDIN] cut [-otpiton][--option][CHAR][FILE]
指令名稱/功能/命令使用者 選項 功能  
cut/
擷取欄位/
Any
-b 擷取單位為 byte 如用於英文語系,效果同選項〝-c〞
-c 擷取單位為字元  
-d "CHAR" 設定自定的欄位間隔  
-f FIELD[,FILED] 設定輸出的欄位 配合選項〝 -d〞或預設的 tab 欄位間隔使用
-s 如某行沒有符合的欄位間隔不輸出  
-n 不分割 mutibyte 字元 用於非英文語系的 mutibyte字元
--output-delimiter 自定輸出的間隔字串  
--help 指令自帶說明  

說明一下比較含糊的選項,因 cut -d 設定欄位時如某行沒有符合的欄位間隔,預設該行會全部輸出,此時可再加選項〝-s〞令其不輸出。

次選項〝--output-delimiter〞可自由設定輸出的間隔字串,如下例把原間隔字元 tab 改字串〝---〞來輸出。

例:
$ echo -e '12\t3\t456\t789' | cut --output-delimiter="---" -f 1- ←自定輸出的間隔字串〝---〞
12--3---456---789

cut 優點為簡單,但相對的缺點就是缺泛彈性,因沒支援正規表示法,以指令 ls -l 為例,如下輸出的間隔為不定長度的空白字元要用 cut 來擷取欄位就要傷腦筋一下。

例:
export TIME_STYLE=long-iso ←設日期/時間格式(不同環境設定會影響〝ls -l〞的輸出格式)
ls -l --time-style=long-iso
drwxr-xy-x  aaa  aaa  4096  2011-09-07  11:44  Desktop 
drwxr-xy-x  aaa  aaa  4096  2011-09-07  11:44  Documents 
-rw-rw-r--   aaa  aaa  2011-08-08  12:42  fileA
-rw-rw-r-- aaa  aaa  12  2011-08-07  12:34  fileB
-rw-rw-r--   aaa  aaa  112  2011-03-08 10:12  MypProject
8 ←欄位數

上例此種空白間隔長度不是固定的或中間有夾雜其他看不見的控制字元(如 tab) 的格式如只想輸出第八個欄位(檔名的位置)以 ls -l | cut -d " " -f8 來擷取欄位結果不會正確,此時有許多方法可考慮。 col 過濾控制字元
如用 man 查某個說明,如下例。

$ man regex

REGEX(3)                   Linux Programmer’s Manual                  REGEX(3)

NAME
regcomp, regexec, regerror, regfree - POSIX regex functions

SYNOPSIS
#include <sys/types.h>
#include <regex.h>


int regcomp(regex_t *preg, const char *regex, int cflags);
int regexec(const  regex_t  *pregconst  char *string, size_t nmatch,
以下略


會發現其說明文件有粗體有底線等所以 man 的文件不是純文字檔,內有許多的控制字元來控制顯示或操作。

有時可能為了方便閱讀或需編輯,用 man regex > regex.txt 把某指令的說明文件存成檔案,此時如用 vi 或其他編輯器來閱讀此檔會出現許多的亂碼,如下。

(vi regex 操作)
REGEX(3)                   Linux Programmer’s Manual                  REGEX(3)



N^HNA^HAM^HME^HE
regcomp, regexec, regerror, regfree - POSIX regex functions

S^HSY^HYN^HNO^HOP^HPS^HSI^HIS^HS
#^H#i^Hin^Hnc^Hcl^Hlu^Hud^Hde^He <^H<s^Hsy^Hys^Hs/^H/t^Hty^Hyp^Hpe^Hes^Hs
以下略

此時可用過濾控制字元程式 col 來過濾文件內的控制字元,其中選項〝-b〞為過濾掉所有已知的控制字元如〝RLF〞(Reverse Line Feed)或〝HRLF〞(Half Reverse Line Feed)或〝HFLF〞(Half Forward Line Feed) 等 。

故上例用 man regex | col -b > regex.txt 會過濾會產生亂碼的控制字元,就可用一般的編輯器來閱讀或編輯。

col 為單字〝colander〞(過濾)的縮寫,很有個性不能直接打開檔案(如 col FILE),只能透過管線(COMMAND | col) 或重定向(如 col -x < FILE > SAVE_FILE) 來操作。

另一選項〝-x〞也很有用,主要為把 tab 轉為連續相對應的空格,如有文件需把 tab 轉空格可多利用。

例:
$ echo -e '12\t\t3\t456\t789' | sed -n 'l' ←用指令〝sed〞讓 tab 現形(顯示 \t)
12\t\t3\t456\t789$
$ echo -e '12\t3\t456\t789' | col -x | sed -n 'l' ←用〝col -x〞把tab 轉為空格
12      3       456     789$

tr 字元轉換
如果應用不複雜只是單純的字元轉換或刪除(注意僅限字元不是字串),tr 可視為 sed 的超級簡化版且幾乎憑直覺就會使用,如下例將字元〝1〞轉換為〝A〞。

例:
$ echo '012345' | tr 1 A ←將字元〝1〞轉換為〝A〞
0A2345

上例中最好將要轉換的字元加上引號「'」或「"」 寫成 echo '012345' | tr '1' 'A' 會比較清楚,tr 有支援 POSIX Character 和範圍〝CHAR1-CHAR2〞這些表示法,如下範例。

例:
$ echo 'abcdef 123 XYZ' | tr 'a-z' 'A-Z' ←將小寫字元轉大寫
ABCDEF 123 XYZ
$ echo 'abcdef 123 XYZ' | tr '[:digit:]' 'i-z' ←將數字轉小寫英文且從 i 開始
abcdef jkl XYZ

也可用 tr 'abcde' 'ijklm' 這種格式,後面的字元〝i〞,〝j〞...〝m〞依序取代前面的〝a〞,〝b〞...〝e〞;但可不是字串〝ijklm〞取代〝abcde〞,如下例為字元〝5〞取代〝i〞和字元〝6〞取代〝s〞;但不是字串〝56〞取代〝is〞(取代字串要用 sed)。

例:
$ echo 'this is a starfruit' | tr 'is' '56'
th56 56 a 6tarfru5t

sed 雖然強大,但處理資料以〝pattern space〞為基礎會去掉結尾的換行來運算故無法處理換行字元,此時用 tr 可輕易完成。

例如早期的蘋果電腦 Mac OS 9 的換行為〝CR〞,如要把 UNIX/Linux 文件給這種古董級電腦來讀取可如下進行轉換:
tr "\n" "\r" < UNIX_FILE > MAC_OS9_FILE

故用 tr 來轉換控制字元也是主功能之一, tr 支援如下的控制字元表示方式,如下表沒列出的也可直接用八進制的 ASCII 碼〝\OCTAL〞(OCTAL 為八進制 ASCII 碼)。

ASCII 控制碼表示法 Dec Hex ASCII 縮寫 名稱/意義
\a 7 7 BEL 響鈴 (bell)
\b 8 8 BS 退格 (backspace)
\t 9 9 TAB 水平定位 (horizontal tab)
\n 10 0A LF 換行 (line feed,new line)
\v 11 0B VT 垂直定位 (vertical tab)
\f 12 0C FF 換頁 (NP form feed, new page)
\r 13 0D CR 回車 (carriage return)
\\ 92 5c   字元〝\〞

除了基本用法 tr 進階用法和選項如下:

語法:[STDIN] tr [-otpiton][--option] CHAR SET1 [CHAR SET2]
指令名稱/功能/命令使用者 選項 功能
tr/
(translate character)字元轉換/
Any
-c 反向選取
-d 刪除字元
-s 刪除連續重複字元
-t 刪除來源字元多於目的字元的部份

選項〝-s〞很常用也很有用,用於刪除連續重複字元(只保留一個)

例:
$ echo "1         2      3   4" | tr -s " " ←刪除多餘的空白
1 2 3 4
$ echo -e "1\t\t\t2      3       4" | tr -s " \t" ←刪除多餘的空白和 tab
1      2 3 4
$ tr -s '\n' < fileA > fileB ←刪除〝fileA〞多餘的空行存成〝fileB〞
$ sed -n '5,20 p' fileA | tr -s "\n" ←刪除〝fileA〞5~20 行內多餘的空行

例:
$ echo 'busy buzzing bumblebees buzzing busying' | tr -d 'busy' ←刪除字元〝b〞,〝u〞,〝s〞或〝y〞(不是刪除字串〝busy〞)。
zzing mleee zzing ing
$ echo -e "1\t\t\t2      3       4" | tr -s " \t" | tr -d " \t" ←先刪除重複的空白和tab 再把空白和 tab 刪除
1234
$ echo 'abcdef 123 XYZ' | tr -d '[:digit:]' ←刪除所有數字
abcdef XYZ
$ tr -d '\r' < DOS_FILE > UNIX_FILE ←刪除 windows/DOS 檔的字元'\r'

上例最後一範例 tr -d '\r' < DOS_FILE > UNIX_FILE 同等於指令 dos2unix

其他選項範例如下:

例:
$ echo 'abcdef 123 XYZ' | tr -c '[:alpha:]' '-' ←把所有非字母的字元轉為字元〝-〞
abcdef-----XYZ-
$ echo 'abcdef 123 XYZ' | tr -t 'abcde' 'AB' ←目的字元只有〝A〞和〝B〞少於來源〝a〞~〝e〞,故只轉換前二個字元
ABcdef 123 XYZ


sort 排序
sort 為將文字以行為單位比較每行的第一個字元由小到大來排序,如第一個字元相同再依次比較下一個字元 。有點討厭的是 sort萬用字元一樣其排序順序會受語系設定影響,如要依 ASCII 碼的順序來排序,要設環境變數〝LANG=C〞。(後續的測試以 LANG=C 為基準)

sort 基本用法很容易,實例看一次就會了,如下有一檔案〝equip〞為公司今年採購的電腦設備清單。

cat equip
xerox         apr 4
acer1         feb 1
XEROX-FUJI    may 5
printer1      oct 6
acer2         oct 10
printer1      jul 3
ASUS1         sep 4
Apple         jun 5
IBM2          dec 7
acer2         oct 10
ASUS2         nov 20
IBM1          mar 1

但這清單給老闆看一定會被打槍,老闆一秒幾十萬上下怎可能有美國時間看這沒整理過的文件,至少用 sort 來排序一下。

例:
$ LANG=C ←設定語系為〝C〞(同等〝LANG=POSIX〞)此時排序是根據 ASCII table
$ sort equip
ASUS1         sep 4
ASUS2         nov 20
Apple         jun 5
IBM1          mar 1
IBM2          dec 7
XEROX-FUJI    may 5
acer1         feb 1
acer2         oct 10
acer2         oct 10
printer1      jul 3
printer1      oct 6
xerox         apr 4

上例好多了,但怪怪的,上面那個〝ASUS〞和〝acer〞一樣是 A 開頭排序順序怎和股價一樣差那麼多?因 ASCII table 的順序是先大寫後小寫。

用選項〝-f〞為不管大小寫(一律視為大寫)重排看看

$ sort -f equip ←選項〝-f〞為不管大小寫
acer1         feb 1
acer2         oct 10
acer2         oct 10
Apple         jun 5
ASUS1         sep 4
ASUS2         nov 20
IBM1          mar 1
IBM2          dec 7
printer1      jul 3
printer1      oct 6
xerox         apr 4
XEROX-FUJI    may 5

經過上頭的排序處理應可交差了。 sort 功能也不止於此如改天我想根據指定的欄位來排序,可用選項〝-k〞,如下例為根據欄位 3 來重排。

$ sort -k 3 equip ←選項〝-k〞,根據指定的欄位來排序
IBM1          mar 1
acer1         feb 1
acer2         oct 10
acer2         oct 10
ASUS2         nov 20
printer1      jul 3
ASUS1         sep 4
以下略

上例注意看還是怪怪的,如是由小排到大第三欄位的〝20〞怎排在〝3〞前?原來 sort 是先排序完第一個字元,如第一個字元相同再依次比較下一個字元,故以第一字元來說〝1x〞〝2x〞永遠排在〝3〞前。
解決方法為用選項〝-n〞,此選項會根據欄位數字的大小排序,如下例。

$ sort -n -k 3 equip ←根據欄位 3 的數字大小排序
acer1         feb 1
IBM1          mar 1
printer11     jul 3
ASUS1         sep 4
xerox         apr 4
Apple         jun 5
XEROX-FUJI    may 5
printer11     oct 6
IBM2          dec 7
acer2         oct 10
acer2         oct 10
ASUS2         nov 20

想排序的欄位如相等sort 還支援在此情況下再比其他欄位,設定多個優先順序,只要再多加選項〝-k〞,如下例為如欄位 2 相等時根據欄位 5。

例:
$ ls -l /etc | sort -k2 -k5 ←欄位 2 相等時根據欄位 5 來排序
以上略

-rw-r--r--  1 root root   77598 Nov 25 00:30 ld.so.cache
-rw-r--r--  1 root root   84649 Aug 23  2007 sensors.conf
-rw-r--r--  1 root root  117276 Sep 17  2007 Muttrc
-rw-r--r--  1 root root  362047 Apr 18  2007 services
-rw-r--r--  1 root root  412666 Jan 26 14:21 prelink.cache
以下略

而選項〝-M〞會根據月份的英文〝JAN〞,〝FEB〞...〝DEC〞(以月份前三個字元的縮寫為基準)來排序。

$ sort -M -k 2 equip ←根據欄位 2 月份來排序
acer1         feb 1
IBM1          mar 1
printer11     jul 3
ASUS1         sep 4
以下略

談一下選項〝-k〞如〝-k 2.3〞表示欄位 2 第 3 字元開始排序。
下例假設你拿到的清單前加了員工使用者的 id ,如下例如你想把 id 濾掉再來排序可指定欄位 1 從第 6 字元開始排序,如下示範。

$ cat equip1 ←清單前被加了員工使用者的 id
id03_xerox        apr 4
id04_XEROX-FUJI   may 5
id06_acer1        feb 1
id05_IBM1         mar 1
id09_IBM2         dec 7
id12_printer1     jul 3
$ sort -k1.6 equip1 ←指定欄位 1 的第 6 個字元開始排序
id06_acer1        feb 1
id05_IBM1         mar 1
id09_IBM2         dec 7
id12_printer1     jul 3
id03_xerox        apr 4
id04_XEROX-FUJI   may 5

sort 其他常用的選項如下:

語法:[STDIN] sort [-otpiton] [FILES]
指令名稱/功能/命令使用者 選項 功能
sort/
排序/
Any
-b 忽略每行前面的空白字元
-d 只考慮空白,數字和字母
-f 忽略大小寫
-g 數字的大小排序,類似選項〝-n〞但可以是科學符號表示法如 〝1.23E10〞
-i 忽略不可列印字元`
-k field[.STAR CHAR] 根據指定的欄位來排序
-M 根據月份的英文〝JAN〞,〝FEB〞...〝DEC〞來排序
-n 根據數字的大小排序
-o FILE 將輸出寫入檔案而不是螢幕
-R 亂數隨機排序
-r 反向排序(由大到小)
-t CHAR 指定間隔字元
-u 刪除排序完重複的行


uniq 刪除相鄰重複的行
指令 uniq 只會刪除相鄰且重複的行,所以一般是用 sort 排序完再用 uniq 來刪除相鄰重複的行或單獨用來刪除重複相鄰的空行。

例:
$ sort equip | uniq > result ←sort 排序完經 uniq 來刪除相鄰重複的行(同等用〝sort -u〞)
$ echo -e 'lineA\nlineA\nlineB' | uniq ←相鄰重複的行才會被刪除
lineA
lineB
$ echo -e 'lineA\nlineB\nlineA' | uniq ←如不相鄰雖有重複的行不會被刪除
lineA
lineB
lineA
$ echo -e 'lineA\n\n\n\n\n\nlineB' | uniq ←刪除中間的空行
lineA

LineB

uniq 功能簡單所以選項也不多,常用的選項如下:

語法:[STDIN] uniq [-otpiton] [FILES]
指令名稱/功能/命令使用者 選項 功能
uniq/
刪除相鄰重複的行/
Any
-c 顯示重複出現的次數
-d 僅顯示相鄰且重複的行
-f # 略過比較的欄位(〝# 〞為欄位數)
-s # 忽略第幾 # 個字元
-u 和〝-d 〞相反,列出只出現一次的行
-w # 每行最多比較第 # 個字元

例:
$ echo -e 'lineA\nLineB\nLineB\nLineC' | uniq -u ←列出只出現一次的行
lineA
LineC
# echo -e 'lineA\nLineB\nLineB\nLineC' | uniq -c ←顯示重複出現的次數
1 lineA
2 LineB
1 LineC
$ uniq -s 9 fileA ←不比較每行的第 9 個字元
$ uniq -w 9 fileA ←只比較毎行前 9 個字元


^ back on top ^