在 Linux 命令中,grep
命令是最經常使用的命令之一。下面基於實例介紹 grep
命令的常見用法。html
查看 man grep 對 grep
命令的說明以下:node
grep [OPTIONS] PATTERN [FILE...]git
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]正則表達式
即,grep
命令在所給文件中查找特定模式的字符串,能夠提供多個文件名,在多個文件中查找。shell
若是沒有提供文件名,則讀取標準輸入。express
默認會打印出包含特定模式的整行內容,以便查看是哪一行包含了這個模式。bash
注意:跟在 grep
命令的 PATTERN 參數後面的參數會被認爲是文件名,即便用引號把參數值括起來也仍是當成文件名,不會當成字符串。less
剛接觸 grep
命令的常見誤區是,覺得用雙引號把參數值括起來就變成查找字符串,這是錯誤的用法。測試
具體舉例說明以下:優化
$ cat testfile This is a test string. $ grep "string" testfile This is a test string. $ grep "string" "testfile" This is a test string. $ grep "string" "This is a test string." grep: This is a test string.: No such file or directory
能夠看到,當前目錄下有一個 testfile 文件,它裏面只有一行 "This is a test string." 字符串。
grep "string" testfile
命令會在 testfile 文件中查找 "string" 字符串,找到後打印出對應的行。
grep "string" "testfile"
命令也是在 testfile 文件中查找 "string" 字符串,即便用雙引號把 testfile 括起來,也不表明是在 "testfile" 字符串中查找 "string" 字符串。
而 grep "string" "This is a test string."
命令會執行報錯,提示找不到名爲 This is a test string. 的文件,它不是在 "This is a test string." 字符串中查找 "string" 字符串。
若是確實須要用 grep
命令來查找字符串,能夠用管道操做符 |
來鏈接標準輸入。
例如用 echo
命令打印字符串的值,而後經過管道操做符把這個值傳遞到 grep
命令的標準輸入。
舉例以下:
$ echo "This is a test string." | grep string This is a test string. $ value="This is a new test string." $ echo "$value" | grep new This is a new test string. $ echo $? 0
能夠看到,echo "This is a test string." | grep string
命令經過 echo
先輸出字符串的值,再經過管道操做符 |
把這個輸出鏈接到 grep
命令的標準輸入,就能查找字符串,不會執行報錯。
echo "$value" | grep new
命令在 value 變量值中查找 "new" 字符串,grep
命令在查找到匹配模式時,會返回 0,也就是 true。
可使用 $?
獲取到命令返回值,檢查這個返回值是否爲 0,就能判斷某個字符串是否爲另外一個字符串的子字符串。
注意:這裏使用管道操做符 |
來鏈接標準輸入,讓 grep
命令可以查找字符串,可是使用重定向標準輸入操做符 <
並不能讓 grep
命令查找字符串。
重定向是基於文件的操做,所給的字符串會被當成文件名。舉例以下:
$ grep "string" < "This is a test string." -bash: This is a test string.: No such file or directory
能夠看到,在重定向標準輸入操做符 <
右邊的 "This is a test string." 字符串被當成文件名,bash 提示找不到文件。
這裏不是 grep
命令報錯,而是 bash 在處理重定向的時候報錯。
在 grep
的命令格式中,默認是一個匹配模式對應多個文件,而不是多個匹配模式對應一個文件。
在 PATTERN 參數後面的全部參數都會認爲是文件名,能夠提供多個文件名,在這些文件中統一查找同一個匹配模式。
舉例說明以下:
$ grep test testfile retestfile testfile:This is a test string. retestfile:retestfile
在上面的 grep test testfile retestfile
命令中,test 是 PATTERN 參數,指定匹配模式,testfile 和 retestfile 都是要查找的文件名,並非在 retestfile 文件中查找 test 模式和 testfile 模式。
在 grep
命令中使用 bash 的星號 *
通配符時,可能就會擴展成查找多個文件的狀況:
$ set -x $ grep *test* testfile + grep --color=auto retestfile testfile testfile $ grep test *test* + grep --color=auto test retestfile testfile retestfile:retestfile testfile:This is a test string. $ set +x
剛接觸 grep
命令和 bash 的星號 *
通配符時,常見的誤區是認爲 grep *test* testfile
命令會在 testfile 文件查找任意包含 test 的字符串。
可是上面的打印結果爲空。打開 bash 調試信息,能夠看到該命令擴展爲 grep --color=auto retestfile testfile testfile
,基於 grep
的命令格式,實際上是在 testfile 文件中查找 "retestfile" 字符串,並且會查找兩次,由於提供了兩次 testfile 文件名。
Bash 的 *
通配符沒有被引號括起來時,其擴展結果來自於當前目錄下的文件名,若是多個文件名符合所給模式,就會把多個文件名做爲參數傳遞給被執行命令,致使被執行命令的參數個數發生變化,要注意這個擴展結果是否符合預期。
能夠看到,grep test *test*
命令的擴展結果是 grep --color=auto test retestfile testfile
,在 retestfile、testfile 這兩個文件中查找 "test" 字符串。
即,認識到 grep
命令是一個匹配模式對應多個文件,有助於理解在命令參數中使用 bash 的 *
通配符、或者其餘通配符時的執行結果。
若是要查找多個匹配模式,要經過其餘選項、或者正則表達式來指定。後面會具體說明。
當 grep
命令的 PATTERN 參數爲空字符串時,會匹配所給文件的全部行。
舉例說明以下:
$ cat testfile This is a test string. $ grep "" testfile This is a test string. $ grep '' testfile This is a test string.
能夠看到,grep "" testfile
命令和 grep '' testfile
命令都匹配了 testfile 文件的全部行。
GNU grep 的在線幫助連接 https://www.gnu.org/software/... 對此進行了說明:
11. Why does the empty pattern match every input line?The grep command searches for lines that contain strings that match a pattern. Every line contains the empty string, so an empty pattern causes grep to find a match on each line.
It is not the only such pattern: ‘^’, ‘$’, ‘.*’, and many other patterns cause grep to match every line.
To match empty lines, use the pattern ‘
^$
’. To match blank lines, use the pattern ‘^[[:blank:]]*$
’.
即,grep
命令認爲每一行都包含空字符串,因此提供的匹配模式爲空字符串時,會匹配到全部行。
匹配模式寫爲 '^'
、'$'
、'.*'
,也是會匹配到全部行。
若是想要匹配空行,匹配模式能夠寫爲 '^$'
,空行只包含一個行末的換行符。
若是想要匹配只包含空白字符(空格、或 tab 字符)的行,匹配模式能夠寫爲 ^[[:blank:]]*$
。
在 Linux 中,grep
命令默認不會顏色高亮匹配到的模式字符串。
若是想要高亮所匹配的部分,須要加上 --color=auto
或者 --color=always
選項纔會顯示顏色高亮。
在一些 Linux 系統上,執行 grep
命令,沒有手動加 --color=auto
也會看到顏色高亮。
這是由於 bash 設置了 alias
別名,默認已經加上 --color=auto
選項。
具體舉例說明以下:
$ alias grep alias grep='grep --color=auto'
能夠看到,bash 設置了 grep 字符串爲 grep --color=auto
命令的別名。
那麼在 bash 中執行 grep
命令,實際執行的是 grep --color=auto
,因此可以顏色高亮。
可使用 \grep
來指定不使用 alias
別名,執行原始的 grep
命令,就能看到沒有顏色高亮。
具體舉例說明以下:
$
grep "string" testfile
This is a test <span style="color:red;">string.</span>
$
grep "string" testfile
This is a test string.
$
grep --color=auto "string" testfile
This is a test <span style="color:red;">string.</span>
在這個測試結果中,只有 \grep "string" testfile
命令確實沒有加 --color=auto
選項,打印的匹配結果沒有顏色高亮。
查看 man grep 對 --color
選項、以及它的取值說明以下:
--color[=WHEN], --colour[=WHEN]Surround the matched (non-empty) strings, matching lines, context lines, file names, line numbers, byte offsets, and separators (for fields and groups of context lines) with escape sequences to display them in color on the terminal.
WHEN is never, always, or auto.
通常來講,當指定爲 always、auto 時,能夠顯示顏色高亮。
當指定爲 never 時,不會顯示顏色高亮。
若是沒有提供 --color
選項,默認值就是 never,不顯示顏色高亮。
注意:在非交互式 shell 中,默認不能使用 alias 別名。
因爲 shell 腳本默認運行在非交互式 shell 下,當在 shell 腳本中使用 grep
命令時,不會自動在 grep
命令後面加上 --color=auto
選項,打印的匹配結果沒有顏色高亮。
在 shell 腳本中執行 grep
命令時,若是想要打印的匹配結果顯示顏色高亮,須要在 shell 腳本的 grep
命令後面主動加上 --color=auto
選項。
查看 man bash 裏面對非交互式 shell 不能使用 alias 別名的說明以下:
Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt.
在 grep
命令的 -r
選項後面能夠提供一個目錄名,指定在所給目錄、及其子目錄的全部文件中進行匹配。
查看 man grep 對 -r
選項的說明以下:
-r, --recursiveRead all files under each directory, recursively, following symbolic links only if they are on the command line. This is equivalent to the -d recurse option.
即,-r
選項指定遞歸讀取所給目錄下的全部文件,默認不處理符號連接文件,除非在命令行參數中提供了符號連接的文件名。
另一個 -R
選項默認會處理符號連接文件,這裏不討論 -R
選項。
注意:-r
選項強調的是讀取目錄下的全部文件,不會匹配目錄名自己,即便目錄名符合指定模式也不會匹配。
而 grep
命令默承認以匹配目錄名自己。
具體舉例以下:
$ grep "string" * grep: string: Is a directory testfile:This is a test string. $ grep "string" -r . ./testfile:This is a test string. $ grep -d skip "string" * testfile:This is a test string.
能夠看到,grep string *
命令的打印結果裏面,有一個 string 目錄名匹配 "string" 字符串模式。
而用 grep "string" -r .
命令查找當前目錄下的全部文件,打印結果沒有匹配到 string 這個目錄名,加了 -r
選項不會再匹配目錄名。
也可使用 -d skip
選項來指定不匹配目錄名,如 grep -d skip "string" *
命令的打印結果所示。
另外,grep "string" *
命令是由 bash 把通配符 *
擴展爲當前目錄下的全部文件名,包括子目錄名自身,但不會遞歸擴展子目錄下的文件名。
而 grep "string" -r .
命令會遞歸查找子目錄下的全部文件。注意這二者的區別。
當使用 grep 命令搜索多個文件時,可使用 --exclude
指定忽略不搜索特定的文件名,或者使用 --exclude
指定只搜索特定的文件名。
查看 man grep 對這兩個選項對說明以下:
--exclude=GLOBSkip any command-line file with a name suffix that matches the pattern GLOB, using wildcard matching;
a name suffix is either the whole name, or a trailing part that starts with a non-slash character immediately after a slash (/) in the name.
A pattern can use *, ?, and [...] as wildcards, and to quote a wildcard or backslash character literally.
--include=GLOB
Search only files whose base name matches GLOB (using wildcard matching as described under --exclude).
即,使用 --exclude=GLOB 指定忽略匹配 GLOB 模式的文件名,可使用 bash 通配符來指定符合所給模式的多個文件名。
使用 --include=GLOB 則是指定只搜索匹配 GLOB 模式的文件名。
grep
命令默認不是全詞匹配,能夠匹配到某個單詞的一部分。若是想要全詞匹配,能夠加上 -w
選項。
查看 man grep 對 -w
選項的說明以下:
-w, --word-regexpSelect only those lines containing matches that form whole words. The test is that the matching substring must either be at the beginning of the line, or preceded by a non-word constituent character.
Similarly, it must be either at the end of the line or followed by a non-word constituent character. Word-constituent characters are letters, digits, and the underscore.
即,「全詞匹配」指的是所匹配單詞的開頭和末尾先後都要是不能組成單詞的字符。可以組成單詞的字符是字母、數字、和下劃線。
具體舉例以下:
$ echo -e "This is a test string.\nThis" > testfile $ grep "is" testfile This is a test string. This $ grep -w "is" testfile This is a test string.
能夠看到,grep "is" testfile
命令會匹配到 "This" 字符串。
而 grep -w "is" testfile
命令不會匹配到 "This" 字符串。
注意:標點符號並非可以組成單詞的字符,字符串後面跟着標點符號並不影響全詞匹配。
舉例以下:
$ grep -w "string" testfile This is a test string.
能夠看到,使用 -w
選項指定全詞匹配 "string" 字符串,可以匹配到包含 "string." 字符串的這一行,單詞後面的標點符號不影響全詞匹配。
不加 -w
選項時,也能夠經過正則表達式來指定全詞匹配。後面會具體說明。
grep
命令在打印匹配行時,默認不顯示該行的行號。若是想要顯示行號,能夠加上 -n
選項。
查看 man grep 對 -n
選項的說明以下:
-n, --line-numberPrefix each line of output with the 1-based line number within its input file.
即,行號的編號從數字 1 開始。具體舉例以下:
$ grep -n "is" testfile 1:This is a test string. 2:This
在匹配行前面打印的數字就是這一行的行號。
grep
命令在匹配時,默認會區分大小寫。例如 "TEST" 模式不能匹配到 "test" 字符串。可使用 -i
選項來指定忽略大小寫。
查看 man grep 對 -i
選項的說明以下:
-i, --ignore-caseIgnore case distinctions in both the PATTERN and the input files.
具體舉例以下:
$ grep "TEST" testfile $ grep -i "TEST" testfile This is a test string.
能夠看到,grep "TEST" testfile
命令沒有匹配到任何內容。
而 grep -i "TEST" testfile
命令指定匹配時忽略大小寫,能夠匹配到 "test" 字符串。
grep
命令默認會打印匹配的行,可使用 -v
選項指定打印不匹配的行,也就是過濾掉匹配的行。
查看 man grep 對 -v
選項說明以下:
-v, --invert-matchInvert the sense of matching, to select non-matching lines.
具體舉例以下:
$ grep -v "test" testfile This
能夠看到,加了 -v
選項後,沒有打印出包含 "test" 模式的 "This is a test string." 這一行,而是打印出不包含 "test" 模式的 "This" 這一行。
grep
命令可使用 -e
選項來分別指定多個模式字符串,每一個模式字符串前面都要加 -e
選項。
查看 man grep 對 -e
的說明以下:
-e PATTERN, --regexp=PATTERNUse PATTERN as the pattern. This can be used to specify multiple search patterns, or to protect a pattern beginning with a hyphen (-).
即,在 -e
選項後面的 PATTERN 參數會被當成要匹配的模式字符串,提供多個 -e
選項就能匹配多個模式字符串。
注意不要在單個 -e
選項後面直接跟多個模式字符串,不然會報錯。
若是所給的模式字符串以 -
字符開頭,grep
命令會認爲是一個選項參數,致使報錯。
此時能夠用 \-
對 -
字符進行轉義,或者用 -e
選項來指定以 -
字符開頭的模式字符串。
具體舉例以下:
$ grep "-test" testfile grep: invalid option -- 't' Usage: grep [OPTION]... PATTERN [FILE]... Try 'grep --help' for more information. $ grep -e "-test" -e "is" testfile This is a test string. New -test string
能夠看到,grep "-test" testfile
命令想要匹配 -test 模式字符串,可是執行報錯,grep
命令把該模式字符串前面的 -t 當成了一個選項。
而 grep -e "-test" -e "is" testfile
命令不會執行報錯,-e "-test"
選項能夠正確識別是要匹配 -test 模式字符串。
-e "-test" -e "is"
這兩個選項指定匹配 -test 模式字符串或 is 模式字符串。
若是不想寫多個 -e
選項,也能夠經過 -E
選項使用擴展正則表達式來匹配多個模式。後面會具體說明。
grep
命令可使用 -G
選項來指定基本正則表達式(basic regular expression)的匹配模式,默認會提供這個選項,能夠不用手動提供。
查看 man grep 對 -G
選項的說明以下:
-G, --basic-regexpInterpret PATTERN as a basic regular expression (BRE). This is the default.
在 man grep 的 REGULAR EXPRESSIONS 小節,對正則表達式語法有所介紹。常見表達式說明以下:
^
匹配行首的空字符串。因爲是匹配空字符串,其實就是匹配到行首,因此 ^This
表示要匹配以 "This" 字符串開頭的行。$
匹配行末的空字符串,也就是匹配到行末。例如 string$
表示匹配以 "string" 字符串結尾的行。\<
匹配單詞開頭的空字符串。例如 \<is
表示匹配以 "is" 開頭的單詞。注意這裏的反斜線 \
並非轉義字符,它是這個表達式自己的一部分。\>
匹配單詞末尾的空字符串。例如 ing\>
表示匹配以 "ing" 結尾的單詞。\<\>
來全詞匹配這兩個表達式中間的單詞。例如 \<is\>
表示全詞匹配 "is" 這個字符串。*
匹配零個或連續多個前面的上一個字符。例如 a*
匹配空字符串、"aa" 字符串、"aaaaaa" 字符串等。[]
來匹配方括號內的任意一個字符。例如 [abc]
能夠匹配字符 a、字符 b、字符 c。還有一些其餘的表達式,後面用到再具體說明。
使用基本正則表達式進行匹配的一些例子說明以下:
$ echo -e "This is a test string.\nNew. This is a testString" > testfile $ grep "^This" testfile This is a test string. $ grep "ing$" testfile New. This is a testString $ grep "\<str" testfile This is a test string. $ grep "String\>" testfile New. This is a testString $ grep "\<test\>" testfile This is a test string.
能夠看到,grep "^This" testfile
匹配以 "This" 開頭的行,沒有匹配 "This" 在中間的行。
grep "ing$" testfile
匹配以 "ing" 結尾的行,不會匹配 "ing." 的狀況,末尾多了標點符號也不匹配。
grep "\<str" testfile
匹配包含以 "str" 開頭的單詞的行。
grep "String\>" testfile
匹配包含以 "String" 結尾的單詞的行。
grep "\<test\>" testfile
全詞匹配包含 "test" 這個單詞的行,跟 grep -w
選項的功能相同。
grep
命令能夠在正則表達式中使用 POSIX 字符類匹配某類特殊字符。
例如在 ASCII 編碼格式下,[:alnum:]
是 A-Za-z0-9
的另外一個寫法,那麼 [[:alnum:]]
至關於 [A-Za-z0-9]
,對應任意一個字母或數字。
注意:在 [:alnum:]
這個寫法中,兩邊的方括號 []
是這個字符類的一部分,並非正則表達式的 []
表達式,要把整個內容再放到方括號 []
裏面,寫成 [[:alnum:]]
纔是有效的正則表達式。
具體舉例以下:
$ grep [:alnum:] testfile grep: character class syntax is [[:space:]], not [:space:] $ grep [[:alnum:]] testfile This is a test string. New. This is a testString
能夠看到,grep [:alnum:] testfile
命令執行報錯,提示正確的語法格式是把 [:space:]
再放到一個方括號 []
裏面。
這裏打印的 [:space:]
是一個舉例的提示,跟該命令提供的 [:alnum:]
無關。
而 grep [[:alnum:]] testfile
命令沒有執行報錯,它會匹配到各個字母、或數字。
參考 GNU grep 在線幫助手冊 https://www.gnu.org/software/...,對 grep
命令支持的各個 POSIX 字符類的說明以下:
POSIX 字符類 | 含義 |
---|---|
[:alnum:] | 字母字符和數字字符 (能夠匹配中文字符) |
[:alpha:] | 字母字符 (能夠匹配中文字符) |
[:blank:] | 空白字符,特指空格和 tab 字符,不包含換行符 |
[:cntrl:] | 控制字符 |
[:digit:] | 數字字符 |
[:graph:] | 圖形字符,包括字母、數字、標點符號,不包括空格 |
[:lower:] | 小寫字符 (不能匹配中文字符) |
[:print:] | 可打印字符,包括字母、數字、標點符號、和空格 |
[:punct:] | 標點符號,也包括運算符、各類括號等 |
[:space:] | 全部空白字符 (空格,製表符,換行符,回車符) |
[:upper:] | 大寫字符 (不能匹配中文字符) |
[:xdigit:] | 十六進制數字 (0-9,a-f,A-F) |
注意:雖然 [:space:]
能夠匹配換行符,可是 grep
命令在讀取文件內容時,會去掉行末的換行符,因此在 grep
中用 [:space:]
匹配不到只有一個換行符的空行。
上面提到,grep
命令默認支持用基本正則表達式來指定匹配模式。除此以外,能夠用 -E
選項來指定使用擴展正則表達式(extended regular expression)。
查看 man grep 對 -E
選項的說明以下:
-E, --extended-regexpInterpret PATTERN as an extended regular expression (ERE).
在 man grep 的 Basic vs Extended Regular Expressions 小節提到了基本正則表達式和擴展正則表達式的區別:
In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions ?, +, {, |, (, and ).
即,比起基本正則表達式,擴展正則表達式在使用一些元字符時,不須要用反斜線 \
進行轉義就能使用。
例如,在基本正則表達式中,+
就表示加號 ‘+’ 這個字符自己,沒有什麼特殊含義,若是想要當成正則表達式元字符,須要寫成 \+
的形式。
而在擴展正則表達式中,+
對應正則表達式的元字符,不用寫成 \+
的形式。
注意:grep
命令使用 GNU BRE 版本的基本正則表達式,GNU BRE 也支持擴展正則表達式的這些元字符,只是要用反斜線 \
進行轉義而已。
而 POSIX 標準定義的 BRE 不支持 ?, +, {, |
這些元字符。
對於部分元字符說明以下:
?
表示匹配零個或一個前面的上一個字符,最多隻能匹配一個字符。+
表示匹配一個或連續多個前面的上一個字符,至少匹配一個字符。|
表示匹配在該元字符前面的模式、或者匹配在該元字符後面的模式。例如,abc|efg
表示匹配 "abc" 字符串、或者匹配 "efg" 字符串。通常經常使用 grep -E
和 |
元字符來指定匹配多個模式,相似於提供多個 -e pattern
選項。
舉例說明以下:
$ grep -E "test string|testString" testfile This is a test string. New. This is a testString $ grep "test string\|testString" testfile This is a test string. New. This is a testString $ grep "test string|testString" testfile
能夠看到,grep -E "test string|testString" testfile
命令能夠查找到包含 "test string" 字符串、或者包含 "testString" 字符串的行。
grep "test string\|testString" testfile
命令不提供 -E
選項,使用 GNU BRE 基本正則表達式,用 \|
對 |
元字符進行轉義,也能查找到包含 "test string" 字符串、或者包含 "testString" 字符串的行。
grep "test string|testString" testfile
命令則什麼都沒有查找到。
如前面說明,可使用相似 echo "$value" | grep pattern
這樣的命令,在 value 變量值中查找 pattern 模式,並檢查 grep
命令的返回值,從而判斷 pattern 模式字符串是否是 value 變量值的子字符串。
這個命令有一個小問題是會打印匹配結果。
對於判斷是否子字符串的需求來講,咱們只須要使用 $?
獲取 grep
命令返回值並進行檢查便可,並不須要看到這個匹配結果。
此時,可使用 -q
選項指定不打印任何內容。
查看 man grep 對 -q
選項的說明以下:
-q, --quiet, --silentQuiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected.
即,-q
選項指定不打印任何內容到標準輸出,即便遇到錯誤也不打印,只會返回命令執行的結果,若是匹配返回 0,不然返回非 0 值。
能夠用 $?
來獲取到這個返回值。
舉例說明以下:
$ grep -q "test" testfile $ echo $? 0 $ grep -q "NONE" testfile $ echo $? 1
能夠看到,grep -q "test" testfile
命令在 testfile 文件中能查找到 "test" 字符串,可是沒有打印出匹配行, echo $?
打印爲 0,說明確實能匹配。
對於查找不到 "NONE" 字符串的狀況,echo $?
打印爲 1。
grep
命令默認只打印包含匹配模式的行,若是想要打印這一行的先後幾行,可使用 -A
、-B
、或 -C
選項。
查看 man grep 對這幾個選項的說明以下:
-A NUM, --after-context=NUMPrint NUM lines of trailing context after matching lines. Places a line containing a group separator (--) between contiguous groups of matches.
-B NUM, --before-context=NUM
Print NUM lines of leading context before matching lines. Places a line containing a group separator (--) between contiguous groups of matches.
-C NUM, -NUM, --context=NUM
Print NUM lines of output context. Places a line containing a group separator (--) between contiguous groups of matches.
即,-A NUM
指定打印匹配行後面的 NUM 行。
-B NUM
指定打印匹配行前面的 NUM 行。
-C NUM
指定打印匹配行先後的 NUM 行,這個選項能夠簡寫爲 -NUM
。
對於這三個選項來講,每個匹配行會打印出多行內容,在不一樣匹配內容塊之間會在打印一個只包含 --
的行來分隔開。
具體舉例說明以下:
$ echo -e "1\n2\n3\n4\n5\n11\n22\n33\n44\n55" > testfile $ grep 3 -A 1 testfile 3 4 -- 33 44 $ grep 3 -B 1 testfile 2 3 -- 22 33 $ grep 3 -C 1 testfile 2 3 4 -- 22 33 44
在這個打印結果中,--
這一行並非 testfile 文件自身的內容,而是 grep
命令打印的分割線。
注意:若是在匹配行的先後內容中包含另外一個匹配行,那麼它們會連在一塊兒打印,並不會重複打印同一個匹配行。
以下面的例子所示:
$ echo -e "1\n2\n3\n33\n4\n5" > testfile $ grep 3 -B 2 testfile 1 2 3 33
能夠看到,匹配到 「3」 這一行時,它上面兩行是 「2」、「1」 這兩行,打印了這兩行。
匹配到 「33」 這一行時,它上面兩行是 「3」、「2」 這兩行,可是並無分隔開來打印這兩行,這兩個匹配行連在一塊兒打印。
即,使用 -A
、-B
、或 -C
選項時,不會出現同一個匹配行被打印兩次的狀況,相鄰匹配行先後內容的同一行也不會被打印兩次。
grep
命令對這些狀況都進行了優化。
當在多個文件中進行查找時,grep
命令會先打印文件名,隨後再打印匹配的行內容。若是隻想打印文件名,不打印匹配的行內容,能夠加上 -l
選項。
查看 man grep 對 -l
選項的說明以下:
-l, --files-with-matchesSuppress normal output; instead print the name of each input file from which output would normally have been printed. The scanning will stop on the first match.
例如,咱們可能想要查看某個變量出如今哪些文件中,若是打印匹配的行內容,可能會有不少輸出,不方便查看文件名,就能夠加上 -l
選項來指定只打印文件名。
舉例以下:
$ grep Fexecute -l -r ./ ./src/kwsearch.c ./src/grep.c ./src/search.h
基於這個打印結果,能夠清楚地看到 Fexecute 變量在上面三個文件中出現過。
在 Linux 中,可使用 find
命令來查找包含特定名稱的文件,而後用 xargs
命令把這些文件名傳給 grep
命令來統一查找特定的模式。
例如,下面命令會查找當前目錄下全部後綴名爲 .c
的文件,而後在這些文件中查找 "main" 字符串:
$ find . -name "*.c" | xargs grep "main"
注意:上面的 xargs
命令必須提供,不然不會查找文件內容。若是寫成 find . -name "*.c" | grep "main"
,那麼是在 find
命令打印的文件名中查找 "main" 字符串,而不是在這些文件名對應的文件內容中進行查找。
另外,xargs
命令調用 grep
時,沒有繼承 bash 的 alias
別名,因此打印結果沒有顏色高亮。若是想要顯示顏色高亮,須要寫爲 xargs grep --color=auto
的形式。