Unix 常用指令 – grep

這裡討論的內容以 FreeBSD 為主,可能會與 linux 系的不同。

grep 是非常重要的指令,可以用來抓取檔案某一行的內容。這個功能非常有用, 舉例來說,假設我想搜尋裡系統上有沒有 chicken 小姐的帳號,我可以這麼做:

>>> grep chicken /etc/passwd

透過搜尋 /etc/passwd 這個檔案的內容有沒有 chicken 這個關鍵字來檢查有沒有這個帳號。 這麼一來,若有這個帳號,grep 就會把那一行列出來,若沒有,就不會輸出任何結果,輸出結果可能會像下面這樣:

chicken:x:1000:1000:chicken,,,:/home/chicken:/bin/tcsh
Code language: JavaScript (javascript)

上面輸出代表系統上確實有親愛的 chicken 小姐的帳號,若什麼都沒有顯示,就表示沒有這個帳號。

除此之外,為了方便從檔案找尋,有時我們也許同時還想知道符合條件的這一行(有 chicken 關鍵字的行)究竟在那一行? 我們就可以再加上參數 -n ,這個參數的意思是在前面新增行號的資訊,比如說:

>>> grep -n chicken /etc/passwd

可能就會輸出下面這樣的結果:

34:chicken:x:1000:1000:chicken,,,:/home/chicken:/bin/tcsh
Code language: JavaScript (javascript)

(最前面的 34 表示這一行的內容是在檔案的第 34 行)

事實上,這個指令並不只能抓取單一檔案的內容,這個指令好用的地方在於它可以一次抓取多個檔案裡面的內容, 不用一個個找尋,我們就可以找出「有那些檔案的某一行有這些內容」的資訊。

比如說我正在寫程式,我若想找這個資料夾有那些檔案的程式碼中有用到 eat() 這個函數, 就可以透過 grep 指令抓取有那些檔案的某一行有包含 eat() 這個字串,輕鬆達成目的。

>>> grep "eat()" *.c
Code language: JavaScript (javascript)

這樣就會把這個資料夾所有包含 eat() 這個字串的每一行都印出來,非常方便。

但若是我只是知道有那些檔案有 eat() 字串而已,這樣輸出的內容可能就太多了, 這時我們就可以加上 -l 這個參數,就會只印出找到符合條件的檔案名稱。

>>> grep -l "eat()" *.c #-l 表示只印出檔案名稱,而不是內容
Code language: CSS (css)

若是想直接抓取某個資料夾裡面所有的內容(包含裡面的所有資料夾),也可以加上 -r 做遞迴搜尋,如:

>>> grep -r -l "eat()" code/ #-l 表示只印出檔案名稱,而不是內容
Code language: PHP (php)

除此之外,我們也可以用 grep 來計數,依此算出某符合的行到底出現幾次。

>>> grep -n chicken /etc/passwd

加上參數 -n 會在符合的行前面顯示出個數,這樣我們就可以知道一共有幾行符合, 不過要注意的是這是指行的次數,所以說若該行出現符合字串的次數不只一次, 它還是會只算一次,所以相對來說,這個功能就比較不實用。

另外,參數 -v 也是非常實用的功能,其代表反轉選取,表示找出所有不符合的行。 比如說,要找出 /var/log/mylog 中,每一個沒有「error」這個字串的行,就可以這麼下:

>>> grep -v error /var/log/mylog
Code language: JavaScript (javascript)

這樣就會秀出沒有出現 error 字串的行了。

最後再補充整理一下一些常見的功能:

參數說明
-n多輸出行號
-l印出符合的檔名
-c印出符合的行數
-v找出不符合的行
-r遞迴找尋資料夾
-i忽略大小寫

發表迴響