最近在看grep的官方文檔,記錄下這些自己練習的例子
準備
新建3個測試文件
# 生成1到100
seq 1 100 > nums.txt
cat>words.txt<<-EOF
hello world
Common methods to solve matrix related problem include DFS, BFS, dynamic programming, etc.
hello123 world123
-hello-
_hello_
EOF
# 生成ASCII表中A到z,包含A-Za-z
printf "%s\n" {A..z} > chars.txt
一、匹配控制
-
-e pattern 模式(即匹配規則),多次使用-e或者和-f使用,會將每個匹配的整合一起,是並集
# 打印包含1或2的行 grep -e "1" -e "2" nums.txt
-
-f file 模式都寫在一個文件中,相當於-e的每個pattern寫在文件中,以行分隔
# 新建文件pattern cat>pattern<<-EOF 1 2 EOF
# 使用-f,與上面使用兩個-e一樣 grep -f pattern nums.txt
-
-i 不區分大小寫
# 匹配[a-c]的行,也可以匹配[A-C] grep -i "[a-c]" chars.txt
-
-v 反轉模式,匹配pattern沒有匹配的行,可以用來排除
# 匹配沒有0-8的行 grep -v [0-8] nums.txt
-
-w 單詞匹配,將pattern作爲一個單詞匹配
僅選擇包含構成整個單詞的匹配項的行。測試結果表明, 匹配的子字符串必須位於行的開頭, 或者前面有一個非單詞的組成字符。同樣, 它必須在行的末尾, 或者後面跟一個非單詞的組成字符。單詞組成字符是字母、數字和下劃線。如果還指定了-x, 則此選項不起作用
# 匹配單詞hello,結果表明-hello-和hello匹配,單詞組成是[0-9a-zA-Z_],其他可作爲單詞分隔 grep -w "hello" words.txt
-
-x 行匹配,僅選擇與整行完全匹配的匹配項。類似於在正則中使用^行首和$行尾完全匹配的一行。
# 可以匹配一行 grep -x "hello world" words.txt # 不匹配 grep -x "hello worl" words.txt
二、輸出控制
- -c 爲每個輸入文件輸出匹配到幾行
# 輸出輸入文件匹配行數 grep -c '1' nums.txt words.txt chars.txt
- -L 打印沒有匹配的輸入文件的名字
grep -L "hello" nums.txt words.txt chars.txt
- -l 打印匹配到的輸入文件的名字
grep -l "hello" nums.txt words.txt chars.txt
- -m num 每個輸入文件最大匹配num次後,停止讀入
grep -m 2 "1" nums.txt words.txt chars.txt
- -o 打印匹配的部分,常用來打印正則匹配的結果
# 打印匹配到的三個數字,正則中注意轉義 grep -o "[0-9]\{3\}" nums.txt words.txt chars.txt
- -q 靜默模式,不會輸出到標準輸出
- -s 不輸出文件不存在或不可讀的錯誤信息。
# aaaaa.txt不存在 grep "1" nums.txt words.txt chars.txt aaaaa.txt grep -s "1" nums.txt words.txt chars.txt aaaaa.txt
三、輸出行前綴控制
當輸出多個前綴字段時, 順序始終是文件名、行號和字節偏移量, 而不考慮指定這些選項的順序
- -b 字節偏移量, 匹配的結果會在文件名後輸出----相對文件開始(0字節)到匹配結果的字節偏移
grep -b "12" nums.txt words.txt
- -H 打印文件名,當超過1個文件時,這個默認生效
# 使用-H,可以當1個輸入文件時顯示文件名 grep -bH "12" nums.txt
- -h 不打印文件名,當只有1個文件時,這是默認設置
# 使用-h,可以當多個輸入文件時不顯示文件名 grep -h "12" nums.txt words.txt
- –label=LABEL 將來自標準輸入看做文件名爲LABEL的文件
# 將標準輸入看做文件名爲myInputFile的文件 cat nums.txt | grep -H "12" --label=myInputFile
- -n 顯示匹配的在輸入文件的行號,作爲輸出的前綴
grep -n "12" nums.txt words.txt
- -T 當輸出一行包含文件名,行號或字符偏移時,會用\t分隔
grep -T "12" nums.txt words.txt
- -u 當使用-b時,會輸出unix風格字節偏移
- -Z 和find -print0’, ‘perl -0’, ‘sort -z’, ‘xargs -0’類似,處理任意文件名,後跟一個NULL字符
# 新建一個文件名包含空格的測試文件 cat>"123 456.txt"<<-EOF hello 123 EOF
# xargs會以空格分隔文件名,當文件名有空格時,以下會報錯 find . -name "*.txt" | xargs grep "hello" # find使用-print0文件名後爲一個NULL,xargs使用-0也以NULL作爲文件分隔,這樣就不會有問題 find . -name "*.txt" -print0 | xargs -0 grep "hello"
# 假設文件名不包含空格時,以下沒問題 grep -l "hello" nums.txt words.txt chars.txt | xargs cat # 當文件名包含空格時,就會出問題 grep -l "hello" nums.txt words.txt chars.txt "123 456.txt" | xargs cat # 打印包含hello的文件所有內容 grep -lZ "hello" nums.txt words.txt chars.txt "123 456.txt" | xargs -0 cat
四、上下文行控制
所謂的上下文行就是在匹配行附近的行,只有當使用下列選項之一時,纔會輸出它們。無論如何設置這些選項,grep都不會多次輸出任何給定行,如果指定了-o選項,則這些選項無效,並且在使用它們時給出警告
- -A num 匹配行後面num行,包含匹配行
# 多文件中,文件名後跟:表示匹配行,-表示附近的行 grep -A 2 "123" nums.txt chars.txt words.txt
- -B num 匹配行前面num行,包含匹配行
grep -B 2 "123" nums.txt chars.txt words.txt
- -C num 或-num,匹配行前後num行,包含匹配行
grep -C 2 "123" nums.txt chars.txt words.txt
五、文件目錄選擇
-
-a 像文本文件一樣處理二進制文件
-
-D action 如果輸入文件是設備、FIFO、Socket ,使用action來處理
如果action爲read, 那麼所有設備像普通文件一樣讀取。
如果action爲skip,那麼自動跳過設備、FIFO、Socket。
默認情況下,如果命令行有設備,或者使用-R(遞歸,目錄下有設備),那麼讀取設備,如果使用-r,則跳過設備。
這個選項對通過標準輸入讀取的文件無效。 -
-d action 如果輸入文件是目錄,使用action來處理。
默認action爲read, 會像普通文件一樣讀取,有些操作系統不允許,那麼就會報錯,或者跳過。在我的測試使用中,可能會卡住。
如果action爲skip,那麼就會跳過目錄。
如果action爲recurse,那麼就遞歸讀取目錄下所有文件,相當於-r。 -
-r 遞歸讀取目錄下文件
六、其他選項
- -E 使用拓展正則表達式
cat>data<<-EOF <a href="http://www.baidu.com">百度一下</a>" hello hellohello able ableable 12321 abcba EOF
# 使用()可以使用組 # 匹配5個字符,迴文字符,類似 12321 grep -oE '(.)(.).\2\1' data # 匹配 hellohello grep -oE '([a-z]{5})\1' data
- -P perl正則,一些正則的高級應用需要用到這個選項
# 獲取鏈接 grep -oP '(?<=href=").*?(?=">)' data
更多細節可以查看官方文檔:http://www.gnu.org/software/grep/manual/grep.html