Linux shell文本三劍客之grep的使用

最近在看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

一、匹配控制

  1. -e pattern 模式(即匹配規則),多次使用-e或者和-f使用,會將每個匹配的整合一起,是並集

    # 打印包含1或2的行
    grep -e "1" -e "2" nums.txt
    
  2. -f file 模式都寫在一個文件中,相當於-e的每個pattern寫在文件中,以行分隔

    # 新建文件pattern
    cat>pattern<<-EOF
    1
    2
    EOF
    
    # 使用-f,與上面使用兩個-e一樣
    grep -f pattern nums.txt
    
  3. -i 不區分大小寫

    # 匹配[a-c]的行,也可以匹配[A-C]
    grep -i "[a-c]" chars.txt
    
  4. -v 反轉模式,匹配pattern沒有匹配的行,可以用來排除

    # 匹配沒有0-8的行
    grep -v [0-8] nums.txt
    
  5. -w 單詞匹配,將pattern作爲一個單詞匹配

    僅選擇包含構成整個單詞的匹配項的行。測試結果表明, 匹配的子字符串必須位於行的開頭, 或者前面有一個非單詞的組成字符。同樣, 它必須在行的末尾, 或者後面跟一個非單詞的組成字符。單詞組成字符是字母、數字和下劃線。如果還指定了-x, 則此選項不起作用

    # 匹配單詞hello,結果表明-hello-和hello匹配,單詞組成是[0-9a-zA-Z_],其他可作爲單詞分隔
    grep -w "hello" words.txt
    
  6. -x 行匹配,僅選擇與整行完全匹配的匹配項。類似於在正則中使用^行首和$行尾完全匹配的一行。

    # 可以匹配一行
    grep -x "hello world" words.txt
    # 不匹配
    grep -x "hello worl" words.txt
    

二、輸出控制

  1. -c 爲每個輸入文件輸出匹配到幾行
    # 輸出輸入文件匹配行數
    grep -c '1' nums.txt words.txt chars.txt
    
  2. -L 打印沒有匹配的輸入文件的名字
    grep -L "hello" nums.txt words.txt chars.txt
    
  3. -l 打印匹配到的輸入文件的名字
    grep -l "hello" nums.txt words.txt chars.txt
    
  4. -m num 每個輸入文件最大匹配num次後,停止讀入
    grep -m 2 "1" nums.txt words.txt chars.txt
    
  5. -o 打印匹配的部分,常用來打印正則匹配的結果
    # 打印匹配到的三個數字,正則中注意轉義
    grep -o "[0-9]\{3\}" nums.txt words.txt chars.txt
    
  6. -q 靜默模式,不會輸出到標準輸出
  7. -s 不輸出文件不存在或不可讀的錯誤信息。
    # aaaaa.txt不存在
    grep "1" nums.txt words.txt chars.txt aaaaa.txt
    grep -s "1" nums.txt words.txt chars.txt aaaaa.txt
    

三、輸出行前綴控制

當輸出多個前綴字段時, 順序始終是文件名、行號和字節偏移量, 而不考慮指定這些選項的順序

  1. -b 字節偏移量, 匹配的結果會在文件名後輸出----相對文件開始(0字節)到匹配結果的字節偏移
    grep -b "12" nums.txt words.txt
    
  2. -H 打印文件名,當超過1個文件時,這個默認生效
    # 使用-H,可以當1個輸入文件時顯示文件名
    grep -bH "12" nums.txt
    
  3. -h 不打印文件名,當只有1個文件時,這是默認設置
    # 使用-h,可以當多個輸入文件時不顯示文件名
    grep -h "12" nums.txt words.txt
    
  4. –label=LABEL 將來自標準輸入看做文件名爲LABEL的文件
    # 將標準輸入看做文件名爲myInputFile的文件
    cat nums.txt | grep -H "12" --label=myInputFile
    
  5. -n 顯示匹配的在輸入文件的行號,作爲輸出的前綴
    grep -n "12" nums.txt words.txt
    
  6. -T 當輸出一行包含文件名,行號或字符偏移時,會用\t分隔
    grep -T "12" nums.txt words.txt
    
  7. -u 當使用-b時,會輸出unix風格字節偏移
  8. -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選項,則這些選項無效,並且在使用它們時給出警告

  1. -A num 匹配行後面num行,包含匹配行
    # 多文件中,文件名後跟:表示匹配行,-表示附近的行
    grep -A 2 "123" nums.txt chars.txt words.txt
    
  2. -B num 匹配行前面num行,包含匹配行
    grep -B 2 "123" nums.txt chars.txt words.txt
    
  3. -C num 或-num,匹配行前後num行,包含匹配行
    grep -C 2 "123" nums.txt chars.txt words.txt
    

五、文件目錄選擇

  1. -a 像文本文件一樣處理二進制文件

  2. -D action 如果輸入文件是設備、FIFO、Socket ,使用action來處理

    如果action爲read, 那麼所有設備像普通文件一樣讀取。
    如果action爲skip,那麼自動跳過設備、FIFO、Socket。
    默認情況下,如果命令行有設備,或者使用-R(遞歸,目錄下有設備),那麼讀取設備,如果使用-r,則跳過設備。
    這個選項對通過標準輸入讀取的文件無效。

  3. -d action 如果輸入文件是目錄,使用action來處理。

    默認action爲read, 會像普通文件一樣讀取,有些操作系統不允許,那麼就會報錯,或者跳過。在我的測試使用中,可能會卡住。
    如果action爲skip,那麼就會跳過目錄。
    如果action爲recurse,那麼就遞歸讀取目錄下所有文件,相當於-r。

  4. -r 遞歸讀取目錄下文件

六、其他選項

  1. -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
    
  2. -P perl正則,一些正則的高級應用需要用到這個選項
    # 獲取鏈接
    grep -oP '(?<=href=").*?(?=">)' data
    

更多細節可以查看官方文檔:http://www.gnu.org/software/grep/manual/grep.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章