UNIX 文字工具: 搜尋

grep 指令的基本功用,是在一個文字檔中搜尋字串, 並將所有含有該字串的整列都輸出到 stdout。 例如

grep Indian indian.txt
所得的結果應該是
three little Indians
six little Indians
nine little Indians
ten little Indian boys
注意,這裡搜尋的道理和在 閱讀工具 中描述的一樣, 所以雖然搜尋的是 Indian 但是 Indians 也會找到。讀者如果實驗
grep it indian.txt
則會看到更多的輸出。

如果只想要知道檔案中有多少列含有 Indian 字串,可以說

grep Indian indian.txt | wc -l
或者,使用 grep 的指令參數 -c (count) 也可以:
grep -c Indian indian.txt
但是兩者的輸出格式不同,讀者應該自己練習。

如果想要把檔案中不含有 Indian 字串的文字列印出來, 可以使用 grep 的指令參數 -v (reverse):

grep -v Indian indian.txt
所得的結果應該是
one little
two little
four little
five little
seven little
eight little

如果想要 grep 不分大小寫,亦即將大寫的 A 和小寫的 a 視為同樣的字元, 則可以使用 grep 的指令參數 -i (ignore cases):

grep -i indian indian.txt

因為 grep 可以從 stdin 輸入資料, 所以如果想要知道含有 Indian 字串的列號,可以說

cat -n indian.txt | grep Indian
或者,使用 grep 的指令參數 -n (line number) 也可以:
grep -n Indian indian.txt
但是兩者的輸出格式不同,讀者應該自己練習。

因為導管的前後可以是同樣的工具軟體, 所以如果想要知道含有 Indian 而且含有 boy 的列文字內容,還有它們的列號, 則可以說

grep -n Indian forty.txt | grep boy
結果應該像是
10:ten little Indian boys
30:    10       ten little Indian boys

grep 可以一次搜尋許多個檔案,其搜尋順序就是按照 ls 指令排列檔案名的順序。 例如

grep boy *.txt
可以印出目前資料夾中所有含有 boy 字串的檔案名,還有它們還有 boy 的那一列文字。 輸出的結果類似
forty.txt:ten little Indian boys
forty.txt:    10    ten little Indian boys
indian.txt:ten little Indian boys
如果還想要知道列號,可以說
grep -n boy *.txt
請讀者自己實驗,看看它的輸出格式。 如果只想知道哪些檔案裡面含有 boy 字串,不在乎它的前後文,也不在乎它在哪裡, 可以用參數 -l (list):
grep -l boy *.txt
有的時候您確定有某項資料寫在某個檔案裡面, 但是不確定寫在哪個檔案裡面了。 這時候,上述指令就可以派上用場。

grep 具有許多的指令參數,用以調整或改變它的搜尋性質。 以上只是初步的介紹。其他的留待讀者較為熟悉 UNIX 系統之後, 自己去學習。

除了 grep 之外,還有 fgrep 和 egrep 兩個同樣性質的工具。 fgrep 的功能比 grep 弱,因此它可能比較快; egrep 的功能比 grep 強,因此它可能比較慢。 基本上 fgrep 完全不接受描述指令,而 egrep 可以接受最完整的描述指令。 在此都不詳述了。


以下是非標準 UNIX 工具。中大數學系的 UNIX 系統有安裝。

運氣好的時候,可以用 grep 在中文檔案裡搜尋中文字串。 但是會遇到兩種問題:

  1. 當中文的 Big-5 字碼之尾碼恰好是 \ ` { } | 這些符號的 ASCII 編號時, 因為 UNIX 或 shell 的設計,可能會產生錯誤。
  2. 當我們要搜尋的字串恰好在詞句中間折列的話,就找不到。例如要搜尋 "計算機",但是文件內容如下:
    在這部教材裡,電腦和電子計算
    機被當做同意詞來使用。
    這是因為 grep 為了英文而設計,在英文純文字檔案中,不會在英文字的中間折列。

為了克服這些困難,我們在 1996 年設計了 cgrep 程式。後來停擺至今,尚未完工, 但是已經可用。cgrep 的基本使用方法,也是

cgrep 字串 FILE
其中字串是指一個 Big-5 碼的中文字串。 針對前述 1. 號困難,我們容許使用者將要搜尋的中文字串寫在一個檔案裡面, 例如 st.txt,然後說
cgrep -f st.txt FILE
則 cgrep 會取 st.txt 的第一列當做搜尋字串。 針對前述 2. 號困難,我們設計一個 -i 指令參數, 使得 cgrep 忽略折列指令不計。 甚至有 -w 參數,使得 cgrep 除了忽略折列指令不計之外, 也忽略每一列最前面、和最後面的連續空白。

cgrep 像 grep 一樣提供 -n 和 -v 這兩種參數,其意義與 grep 的參數相同。 cgrep 的主要缺點,是還不能一次搜尋多個檔案。而且不能接受描述指令。 事實上,我們還沒定義中文的描述指令。

習題

[ 前一節 ]‧[ 後一節 ]‧[ 回目錄 ]



注意:此處所有文件均為原著,個別的版權宣告日後會一一公布, 整體版面設計亦尚未完成。但仍請勿抄襲文字與圖片,以免觸犯著作權法。

Created: Nov 19, 2000
Last Revised: Nov 19, 2000
© Copyright 2000 Wei-Chang Shann 單維彰

shann@math.ncu.edu.tw