grep精確匹配搜尋某個單詞的用法 (附: grep高效用法小結))

散盡浮華發表於2018-07-12

 

grep(global search regular expression(RE) and print out the line,全面搜尋正規表示式並把行列印出來)是一種強大的文字搜尋工具,它能使用正規表示式搜尋文字,並把匹配的行列印出來。

使用grep搜尋某個關鍵字時,預設搜尋出來的是所有包含該關鍵字的行,如下:
搜尋/var/named/veredholdings.cn_zone檔案中172.16.50.24所在的行,預設會把所有包括172.16.50.24所在的行列印出來。
[root@uatdns01 ~]# cat /var/named/veredholdings.cn_zone|grep 172.16.50.24
devzl-app01                   IN      A       172.16.50.243
devzl-app02                   IN      A       172.16.50.244
devzl-redis01                 IN      A       172.16.50.245
devzl-redis02                 IN      A       172.16.50.246
devzl-redis03                 IN      A       172.16.50.247
devzl-oracle01               IN      A       172.16.50.242
wiki02                            IN      A       172.16.50.24

[root@uatdns01 ~]# cat /var/named/veredholdings.cn_zone|grep 172.16.50.24 --color
devzl-app01                   IN      A       172.16.50.243
devzl-app02                   IN      A       172.16.50.244
devzl-redis01                 IN      A       172.16.50.245
devzl-redis02                 IN      A       172.16.50.246
devzl-redis03                 IN      A       172.16.50.247
devzl-oracle01               IN      A       172.16.50.242
wiki02                            IN      A        172.16.50.24

[root@uatdns01 ~]# cat /var/named/veredholdings.cn_zone|grep -o 172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24
172.16.50.24

要想精確地搜尋出檔案中某個單詞所在的行,而不是列印所有包括該單詞字樣的行,可以使用grep -w引數
-w(--word-regexp):表示強制PATTERN僅完全匹配字詞
[root@uatdns01 ~]# cat /var/named/veredholdings.cn_zone|grep -w 172.16.50.24
wiki02                        IN      A       172.16.50.24
或者使用grep "\<\>"形式也可以實現精確匹配
[root@uatdns01 named]# cat /var/named/veredholdings.cn_zone|grep "\<172.16.50.24\>"
wiki02                        IN      A       172.16.50.24

====================面試時給出下面兩個簡單問題===================
1)精確地找出名為abc的程式名。
   ps -ef|grep -w abc
   或者
   ps -ef|grep "\<abc\>"
2)判斷該程式的數量是否在3-5之間。
   ps -ef|grep -w abc|wc -l
   或者
   ps -ef|grep "\<abc\>"|wc -l

===============看一例grep精準匹配的shell案例===============

寫一個shell指令碼,檢查伺服器上的main程式在不在

[root@two002 tmp]# ps -ef|grep main
root     23448 23422  0 11:40 pts/0    00:00:00 grep --color=auto main
[root@two002 tmp]# ps -ef|grep main|grep -v grep|wc -l
0
 
[root@two002 tmp]# cat /tmp/main_check.sh 
#!/bin/bash
NUM=$(ps -ef|grep main|grep -v grep|wc -l)
if [ $NUM -eq 0 ];then
   echo "It's not good! main is stoped!"
else
   echo "Don't worry! main is running!"
fi


執行檢查指令碼
[root@two002 tmp]# sh -x /tmp/main_check.sh
++ grep main
++ grep -v grep
++ wc -l
++ ps -ef
+ NUM=2
+ '[' 2 -eq 0 ']'
+ echo 'Don'\''t worry! main is running!'
Don't worry! main is running!

[root@two002 tmp]# sh /tmp/main_check.sh
Don't worry! main is running!


如上發現,執行指令碼/tmp/main_check.sh的過程中,看到NUM引數值是2!
但是手動執行ps -ef|grep main|grep -v grep|wc -l的結果明明是0!!

這是由於grep匹配的問題,需要grep進行精準匹配,即"grep -w"
這就需要將main_check.sh指令碼內容修改如下:
[root@two002 tmp]# cat /tmp/main_check.sh 
#!/bin/bash
NUM=$(ps -ef|grep -w main|grep -v grep|wc -l)
if [ $NUM -eq 0 ];then
   echo "Oh!My God! It's broken! main is stoped!"
else
   echo "Don't worry! main is running!"
fi


再次執行檢查指令碼,就正確了
[root@two002 tmp]# sh -x /tmp/main_check.sh
++ grep -w main
++ grep -v grep
++ wc -l
++ ps -ef
+ NUM=0
+ '[' 0 -eq 0 ']'
+ echo 'Oh!My God! It'\''s broken! main is stoped!'
Oh!My God! It's broken! main is stoped!

[root@two002 tmp]# sh /tmp/main_check.sh
Oh!My God! It's broken! main is stoped!

================grep選項集錦====================
-a       不要忽略二進位制資料。
-A      <顯示列數> 除了顯示符合範本樣式的那一行之外,並顯示該行之後的內容。
-b       在顯示符合範本樣式的那一行之外,並顯示該行之前的內容。
-c       計算符合範本樣式的列數。
-C      <顯示列數>或-<顯示列數>  除了顯示符合範本樣式的那一列之外,並顯示該列之前後的內容。
-d       <進行動作> 當指定要查詢的是目錄而非檔案時,必須使用這項引數,否則grep命令將回報資訊並停止動作。
-e       <範本樣式> 指定字串作為查詢檔案內容的範本樣式。
-E       將範本樣式為延伸的普通表示法來使用,意味著使用能使用擴充套件正規表示式。
-f        <範本檔案> 指定範本檔案,其內容有一個或多個範本樣式,讓grep查詢符合範本條件的檔案內容,格式為每一列的範本樣式。
-F       將範本樣式視為固定字串的列表。
-G      將範本樣式視為普通的表示法來使用。
-h       在顯示符合範本樣式的那一列之前,不標示該列所屬的檔名稱。
-H       在顯示符合範本樣式的那一列之前,標示該列的檔名稱。
-i         忽略字元大小寫的差別。
-l         列出檔案內容符合指定的範本樣式的檔名稱。
-L        列出檔案內容不符合指定的範本樣式的檔名稱。
-n         在顯示符合範本樣式的那一列之前,標示出該列的編號。
-q        不顯示任何資訊。
-R/-r    此引數的效果和指定“-d recurse”引數相同。
-s        不顯示錯誤資訊。
-v        反轉查詢。
-w       只顯示全字元合的列。
-x        只顯示全列符合的列。
-y        此引數效果跟“-i”相同。
-o        只輸出檔案中匹配到的部分。

========================grep常用示例========================
1)在檔案中搜尋一個單詞,命令會返回一個包含"match_pattern"的文字行:
[root@test ~]# grep match_pattern file_name
2)在多個檔案中查詢:
[root@test ~]# grep "match_pattern" file_1 file_2 file_3 ...
3)輸出除之外的所有行 -v 選項:
[root@test ~]# grep -v "match_pattern" file_name
4)標記匹配顏色 --color=auto 選項:
[root@test ~]# grep "match_pattern" file_name --color=auto
5)使用正規表示式 -E 選項:
[root@test ~]# grep -E "[1-9]+"

[root@test ~]# egrep "[1-9]+"
6) 只輸出檔案中匹配到的部分 -o 選項:
[root@test ~]# echo this is a test line. | grep -o -E "[a-z]+\."
line.
[root@test ~]# echo this is a test line. | egrep -o "[a-z]+\."
line.
7)統計檔案或者文字中包含匹配字串的行數 -c 選項:
[root@test ~]# grep -c "text" file_name
8)輸出包含匹配字串的行數 -n 選項:
[root@test ~]# grep "text" -n file_name

[root@test ~]# cat file_name | grep "text" -n
9)多個檔案
[root@test ~]# grep "text" -n file_1 file_2
10)列印樣式匹配所位於的字元或位元組偏移:
[root@test ~]# echo gun is not unix | grep -b -o "not"
7:not
#一行中字串的字元便宜是從該行的第一個字元開始計算,起始值為0。選項 -b -o 一般總是配合使用。
11)搜尋多個檔案並查詢匹配文字在哪些檔案中:
[root@test ~]# grep -l "text" file1 file2 file3...

grep遞迴搜尋檔案
12)在多級目錄中對文字進行遞迴搜尋:
[root@test ~]# grep "text" . -r -n
.表示當前目錄。
13)忽略匹配樣式中的字元大小寫:
[root@test ~]# echo "hello world" | grep -i "HELLO"
hello
14)選項 -e 制動多個匹配樣式:
[root@test ~]# echo this is a text line | grep -e "is" -e "line" -o
is
is
line
15)也可以使用-f選項來匹配多個樣式,在樣式檔案中逐行寫出需要匹配的字元。
[root@test ~]# cat patfile
aaa
bbb
[root@test ~]# echo aaa bbb ccc ddd eee | grep -f patfile -o

在grep搜尋結果中包括或者排除指定檔案:
16)只在目錄中所有的.php和.html檔案中遞迴搜尋字元"main()"
[root@test ~]# grep "main()" . -r --include *.{php,html}
17)在搜尋結果中排除所有README檔案
[root@test ~]# grep "main()" . -r --exclude "README"
18)在搜尋結果中排除filelist檔案列表裡的檔案
[root@test ~]# grep "main()" . -r --exclude-from filelist
19)使用0值位元組字尾的grep與xargs:
#測試檔案:
[root@test ~]# echo "aaa" > file1
[root@test ~]# echo "bbb" > file2
[root@test ~]# echo "aaa" > file3
[root@test ~]# grep "aaa" file* -lZ | xargs -0 rm
20)執行後會刪除file1和file3,grep輸出用-Z選項來指定以0值位元組作為終結符檔名(\0),xargs -0 讀取輸入並用0值位元組終結符分隔檔名,然後刪除匹配檔案,-Z通常和-l結合使用。
grep靜默輸出:
[root@test ~]# grep -q "test" filename
不會輸出任何資訊,如果命令執行成功返回0,失敗則返回非0值。一般用於條件測試。

列印出匹配文字之前或者之後的行:
21)顯示匹配某個結果之後的3行,使用 -A 選項:
[root@test ~]# seq 10 | grep "5" -A 3
5
6
7
8
22)顯示匹配某個結果之前的3行,使用 -B 選項:
[root@test ~]# seq 10 | grep "5" -B 3
2
3
4
5
23)顯示匹配某個結果的前三行和後三行,使用 -C 選項:
[root@test ~]# seq 10 | grep "5" -C 3
2
3
4
5
6
7
8
24)如果匹配結果有多個,會用"--"作為各匹配結果之間的分隔符:
[root@test ~]# echo -e "a\nb\nc\na\nb\nc" | grep a -A 1
a
b
--
a
b
[root@test ~]# grep "match_pattern" file_name

相關文章