天天看點

shell程式設計-grep指令三劍客之grep指令

三劍客之grep指令

一 grep介紹

grep指令主要用于過濾文本,grep家族如下

grep: 在檔案中全局查找指定的正規表達式,并列印所有包含該表達式的行
egrep:擴充的egrep,支援更多的正規表達式元字元
fgrep:固定grep(fixed grep),有時也被稱作快速(fast grep),它按字面解釋所有的字元
           

grep指令格式如下

grep [選項] PATTERN 檔案1 檔案2 ...

[[email protected] ~]# grep 'root' /etc/passwd
[[email protected] ~]# fgrep 'bash' /etc/passwd

找到:				grep傳回的退出狀态為0
沒找到:			grep傳回的退出狀态為1
找不到指定檔案:	  grep傳回的退出狀态為2
           

grep 指令的輸入可以來自标準輸入或管道,而不僅僅是檔案,例如:

二 選項

-n, --line-number			在過濾出的每一行前面加上它在檔案中的相對行号
-o, --only-matching			隻顯示比對的内容
-q, --quiet, --silent		靜默模式,沒有任何輸出,得用$?來判斷執行成功沒有,即有沒有過濾到想要的内容
--color						顔色
-i, --ignore-case			忽略大小寫
-A, --after-context=NUM		如果比對成功,則将比對行及其後n行一起列印出來
-B, --before-context=NUM	如果比對成功,則将比對行及其前n行一起列印出來
-C, --context=NUM			如果比對成功,則将比對行及其前後n行一起列印出來
-c, --count					如果比對成功,則将比對到的行數列印出來
-v, --invert-match			反向查找,隻顯示不比對的行
-w							比對單詞
-E							等于egrep,擴充



-l, --files-with-matches	如果比對成功,則隻将檔案名列印出來,失敗則不列印
							通常-rl一起用,grep -rl 'root' /etc 
-R, -r, --recursive			遞歸
           

案例:

1、-n # 過濾出所有帶有root的行并顯示行号
[[email protected] ~]# grep -n 'root' /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin

2、-o # 過濾出所有的root并列印出來
[[email protected] ~]# grep -o 'root' /etc/passwd
root
root
root
root

3、-q # 靜默模式
[[email protected] ~]# grep -q 'root' /etc/passwd 
[[email protected] ~]# echo $?
0

4、--color # 帶有顔色過濾
[[email protected] ~]# grep --color -no 'xiaoxu' /etc/passwd
25:xiaoxu
25:xiaoxu
    預設做過别名
[[email protected] ~]# alias
alias grep='grep --color=auto'


5、-i #忽略大小寫
[[email protected] ~]# echo "XIAOXU" | grep -i xiaoxu
XIAOXU

6、-A\-B\-C
# 列印比對行及比對行的後2行
[[email protected] ~]# grep -A 2 'root' /etc/passwd

# 列印比對行及比對行的前2行
[[email protected] ~]# grep -B 2 'root' /etc/passwd

# 列印比對行及比對行的前後兩行都列印
[[email protected] ~]# grep -C 2 'root' /etc/passwd


7、-c # 将比對到的行數列印出來
[[email protected] ~]# grep -c 'root' /etc/passwd
2

8、-v # 反向查找[取反]
[[email protected] ~]# grep -v 'root' /etc/passwd  列印所有不比對此規則的行。
[[email protected] ~]# ps aux | grep nginx | grep -v grep
[[email protected] ~]# ps aux | grep [n]ginx

9、-w # 過濾單詞
[[email protected] ~]# netstat -an |grep -w 80
tcp6       0      0 :::80                   :::*                    LISTEN    
[[email protected] ~]# netstat -an |grep  '\<80\>'
tcp6       0      0 :::80                   :::*                    LISTEN    
[[email protected] ~]# netstat -an |grep  '\b80\b'
tcp6       0      0 :::80                   :::*                    LISTEN   
                        
                        
# 10、-rl
[[email protected] ~]# grep -rl 'root' /etc/    # 将/etc目錄下所有包含'root'内容的檔案都列出來
           

三 正規表達式

3.1 正規表達式介紹

正規表達式,又稱規則表達式**。**(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),是計算機科學的一個概念。正規表達式由元字元組成,通常被用來檢索、替換那些符合某個模式(規則)的文本(許多程式設計語言都支援利用正規表達式進行字元串操作)。

元字元:是一類可以表達出超越其字面本身含義的特殊字元

shell元字元(也稱為通配符): 由shell解釋器來解析,如rm -rf *.pdf,元字元*Shell将其解析為任意多個字元
正規表達式元字元		 : 由各種執行模式比對操作的程式來解析,比如vi、grep、sed、awk

例如:vim示例:
:1,$ s/tom/EGON/g		 # 如anatomy、tomatoes及tomorrow中的“tom”被替換了,而Tom确沒被替換
:1,$ s/\<[Tt]om\>/EGON/g
           

3.2 正規表達式元字元

3.2.1 基本正則元字元集

#元字元		#功能										   #示例	

^ 			  行首										^love
$ 			  行尾										 love$
. 			  除了換行符以外的任意單個字元					 l..e
* 			  前導字元的零個或多個						    ab*love
.* 			  所有字元										a.*love
[] 			  字元組内的任一字元								 [lL]ove
[^] 		  對字元組内的每個字元取反(不比對字元組内的每個字元)   [^a-z0-9]ove
^[^] 	      非字元組内的字元開頭的行

[a-z] 		  小寫字母
[A-Z] 		  大寫字母
[a-Z] 	      小寫和大寫字母
[0-9] 	      數字

\	  		  用來轉義元字元 									  love\.	
\< 		     詞首定位符 單詞一般以空格或特殊字元做分隔、連續的字元組成  \<love
\> 			 詞尾定位符										   love\>
\(..\)		  比對稍後将要使用的字元的标簽	                \(love\)able\1er	
                                                         :1,$ s/\(192.168.11\).66/\1.50/g

x\{m\}			字元x重複出現m次							     e\{3\}
x\{m,\}			字元x重複出現m次以上								e\{3,\}						
x\{m,n\}		字元x重複出現m到n次								e\{3,6\}	
           

示例

# 1、^ 行首
[[email protected] ~]# grep '^root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
 

# 2、$ 行尾
[[email protected] ~]# grep 'bash$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
user1:x:1002:1003::/home/user1:/bin/bash
egon1:x:198:1005::/home/egon1:/bin/bash
gg:x:1004:1006::/home/gg:/bin/bash
egon:x:1005:1007::/home/egon:/bin/bash
tom:x:1006:1008::/home/tom:/bin/bash



# 3、. 除了換行符以外的任意單個字元
[[email protected] ~]# grep 'r..t' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin


# 4、* 前導字元的零個或多個
[[email protected] ~]# cat a.txt 
a
ab
abb
abbb
bbbbb
[[email protected] ~]# grep 'ab*' a.txt 
a
ab
abb
abbb

# 5、.* 所有字元=貪婪
[[email protected] ~]# cat a.txt 
a123+-*/c11113333c
a1c
a77Ac
a23333c
ac
111
222
333
[[email protected] ~]# grep 'a.*c' a.txt 
a123+-*/c11113333c
a1c
a77Ac
a23333c
ac

# 5.1 .*?=》非貪婪,預設情況下,grep不支援非貪婪修飾符,但您可以使用grep -P來使用Perl文法來支援.*?
[[email protected] ~]# cat a.txt 
<a href="http://www.baidu.com">"我他媽的是百度"</a>
<a href="http://www.sina.com.cn">"我特麼的是新浪"</a>


[[email protected] ~]# grep -o 'href=".*" target="_blank" rel="external nofollow" ' a.txt  # 貪婪
href="http://www.baidu.com">"我他媽的是百度"
href="http://www.sina.com.cn">"我特麼的是新浪"

[[email protected] ~]# grep -oP 'href=".*?" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" ' a.txt  # 非貪婪
href="http://www.baidu.com"
href="http://www.sina.com.cn"

[[email protected] ~]# grep -Po 'href=".*?" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" ' a.txt | cut -d= -f2
"http://www.baidu.com"
"http://www.sina.com.cn"


# 6、[] 字元組内的任一字元
# 7、[^] 對字元組内的每個字元取反(不比對字元組内的每個字元)
[[email protected] ~]# cat a.txt 
a1c
a2c
a33c
aAc
aZc
[[email protected] ~]# grep 'a[0-9]c' a.txt
a1c
a2c
[[email protected]gon ~]# grep 'a[^0-9]c' a.txt
aAc
aZc
[[email protected] ~]# 
[[email protected] ~]# grep 'a[0-9][0-9]c' a.txt
a33c
[[email protected] ~]# 

# 8、^[^] 非字元組内的字元開頭的行
[[email protected] ~]# cat a.txt 
a1c
a2c
a33c
aAc
aZc
[[email protected] ~]# grep '^[^0-9]..$' a.txt
a1c
a2c
aAc
aZc
[[email protected] ~]# 

# 9、[a-z] 小寫字母
# 10、[A-Z] 大寫字母
# 11、[a-Z] 小寫和大寫字母
# 12、[0-9] 數字

# 13、\< 單詞頭 單詞一般以空格或特殊字元做分隔,連續的字元串被當做單詞
# 14、\> 單詞尾
[[email protected] ~]# netstat -an |grep -w 80
tcp6       0      0 :::80                   :::*                    LISTEN    
[[email protected] ~]# netstat -an |grep  '\<80\>'
tcp6       0      0 :::80                   :::*                    LISTEN    
[[email protected] ~]# netstat -an |grep  '\b80\b'
tcp6       0      0 :::80                   :::*                    LISTEN   
           

Ps: grep比對換行符和制表符

[[email protected] ~]# echo -e "a\nb" |grep $'a\nb'
a
b
[[email protected] ~]# 
[[email protected] ~]# echo -e "a\tb" |grep $'a\tb'
a	b
           

3.2.2 擴充正則元字元集

# 擴充正則元字元
+					比對一個或多個前導字元		   [a-z]+ove	
?					比對零個或一個前導字元		   lo?ve	
a|b					比對a或b					love|hate
()					組字元						love(able|rs)  (egon)+
(..)(..)\1\2		标簽比對字元				  (love)able\1er
x{n}			    x出現n次				    e{3}		
x{n,}			    x出現n次至無窮次			  e{3,}
x{n,m}		        x出現n次至m次			   e{3,6}

# 若想使用擴充正則
grep加-E 或 egrep 或轉義\

sed 加 -r 參數 或轉義

AWK 直接支援大多數擴充正則,更多支援需要加選項--posix選項
           

示例

# ======================grep擴充正則示例======================
[[email protected] ~]# cat a.txt 
a

ab
abb
abbb
abbbb
abbbbb
bbbbbbb
[[email protected] ~]# grep 'ab{2,4}' a.txt  # 預設不支援擴充正則,是以沒效果
[[email protected] ~]# egrep 'ab{2,4}' a.txt 
abb
abbb
abbbb
abbbbb
[[email protected] ~]# 

# ======================sed擴充正則示例======================
[[email protected] ~]# sed -n '/roo?/p' /etc/passwd  # 預設不支援擴充正則?
[[email protected] ~]# sed -n '/roo\?/p' /etc/passwd  # 可以用\轉義擴充正則符号?
有結果,結果略...
[[email protected] ~]# sed -rn '/roo?/p' /etc/passwd  # 也可以加-r選項
有結果,結果略...
[[email protected] ~]# 

# ======================awk擴充正則示例======================
[[email protected] ~]# cat a.txt 
a

ab
abb
abbb
abbbb
abbbbb
bbbbbbb
[[email protected] ~]# awk '/ab{1,3}/{print}' a.txt
ab
abb
abbb
abbbb
abbbbb
[[email protected] ~]# awk --posix '/ab{1,3}/{print}' a.txt
ab
abb
abbb
abbbb
abbbbb
           

總結

grep:				使用基本元字元集	^, $, ., *, [], [^], \< \>,\(\),\{\}
egrep(或grep -E):	使用擴充元字元集	?, +, { }, |, ( )
# 注:grep也可以使用擴充集中的元字元,僅需要對這些元字元前置一個反斜線

\w	所有字母與數字,稱為字元[a-zA-Z0-9]	   'l[a-zA-Z0-9]*ve'	   		'l\w*ve'
\W	所有字母與數字之外的字元,稱為非字元	   'love[^a-zA-Z0-9]+' 	        'love\W+'
\b	詞邊界								'\blove\b'					  '\<love\>'
           

3.2.3 posix定義的字元分類

# 表達式       	  功能                              			示例
[:alnum:]     	字母與數字字元                       		[[:alnum:]]+  
[:alpha:]  		字母字元(包括大小寫字母)					  [[:alpha:]]{4}
[:blank:]     	空格與制表符                         		  [[:blank:]]*
[:digit:]       	數字字母                            	[[:digit:]]?
[:lower:]      	小寫字母                            		[[:lower:]]{5,}
[:upper:]      	大寫字母                            		[[:upper:]]+
[:punct:]      	标點符号                            		[[:punct:]]
[:space:]      	包括換行符,回車等在内的所有空白[[:space:]]+


# 詳解
[:alnum:] Alphanumeric characters.
比對範圍為 [a-zA-Z0-9]
[:alpha:] Alphabetic characters.
比對範圍為 [a-zA-Z]
[:blank:] Space or tab characters.
比對範圍為 空格和TAB鍵
[:cntrl:] Control characters.
比對控制鍵 例如 ^M 要按 ctrl+v 再按回車 才能輸出
[:digit:] Numeric characters.
比對所有數字 [0-9]
[:graph:] Characters that are both printable and visible. (A space is print-
able, but not visible, while an a is both.)
比對所有可見字元 但不包含空格和TAB 就是你在文本文檔中按鍵盤上能用眼睛觀察到的所有符号
[:lower:] Lower-case alphabetic characters.
小寫 [a-z]
[:print:] Printable characters (characters that are not control characters.)
比對所有可見字元 包括空格和TAB
能列印到紙上的所有符号
[:punct:] Punctuation characters (characters that are not letter, digits, con-
trol characters, or space characters).
特殊輸入符号 +-=)(*&^%$#@!~`|\"'{}[]:;?/>.<,
注意它不包含空格和TAB
這個集合不等于^[a-zA-Z0-9]
[:space:] Space characters (such as space, tab, and formfeed, to name a few).

[:upper:] Upper-case alphabetic characters.
大寫 [A-Z]
[:xdigit:] Characters that are hexadecimal digits.
16進制數 [0-f]

# 使用方法:
[[email protected] ~]# grep --color '[[:alnum:]]' /etc/passwd
           

四 練習

正規表達式及字元處理

目标檔案/etc/passwd,使用grep指令或egrep
1.顯示出所有含有root的行:
2.輸出任何包含bash的所有行,還要輸出緊接着這行的上下各兩行的内容:
3.  顯示出有多少行含有nologin。
4.顯示出那些行含有root,并将行号一塊輸出。
5.顯示出檔案中
6.建立使用者
    abominable
    abominate
    anomie
    atomize
    編寫正規表達式,将他們比對出來
    egrep 'a.omi(nabl|nat|z|)e' /etc/passwd
7.建四個使用者
    Alex213sb
    Wpq2222b
    yH438PIG
    egon666
    egon

    過濾出使用者名組成是字母+數字+字母的行
[[email protected]-R3-srv ~]# egrep '^[a-Z]+[0-9]+[a-Z]+' /etc/passwd
8.顯示出/etc目錄下所有包含root的檔案名
9. 過濾掉/etc/ssh/sshd_config内所有注釋和所有空行
grep -v '^#' /etc/ssh/sshd_config |grep -v '^ *$'
           

繼續閱讀