亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

Shell 正則表達式

1. Shell 正則表達式概述

1.1 正則表達式是什么

正則表達式 (regular expression)是一些具體有特殊含義的符號,組合在一起的共同描述字符或字符串的方法,通俗來講正則為描述同一類事物的規則,例如我們生活中描述可以飛行的是事物,則滿足這條規則的可以是鳥,蝴蝶,也可以是飛機等。

在 Linux 系統中,正則表達式通常用來對字符或字符串來進行處理,它是用于描述字符排列或匹配模式的一種語言規則。

1.2 為什么要用正則表達式

我們知道正則表達式是一個描述字符排列或模式匹配的規則,我們可以利用它來制定自己的規則,獲取到我們想要的結果等。在后續的 Shell 三劍客 grep/awk/sed Shell 的學習中,我們會結合正則表達式與這些命令進行結合使用,來實現更強大的文本處理功能。正則表達式是我們 Shell 學習的核心也是難點,在 Linux 中一切皆文件,多文件的處理可以覆蓋我們日常工作的 90%,所有熟練掌握正則表達式顯得尤為重要,在之后靈活配合其他命令可以非常方便的滿足我們的日常處理需求。

2. Shell 正則表達操作

在學習正則表達式的操作之前我們需要了解下 POSIX 及正則表達式的分類。

2.1 預備知識

2.1.1 POSIX

POSIX 稱為:Portable Operating System Interface(末尾增加 X 只是為了更流暢)的縮寫,后來被 IEEE 采納,由于在早期 Unix 系統時代各廠商發布不同版本的操作系統,各版本之間存在著產品的差異,之后 IEEE 發布了一套 Unix 和類 Unix 系統工作方式規范,至此各常見遵循此規范來達到軟件兼容的效果。

2.1.2 正則表達式分類

正則表達式常見的有兩種分類:

  • 基本正則表達式:Basic Regular Expression 又叫 Basic RegEx 簡稱 BREs,在基本正則表達式中作用的元字符為:^ 、$. 、[、]* ;
  • 擴展正則表達式:Extended Regular Expression 又叫 Extended RegEx 簡稱 EREs,其為在基本正則表達式上新增了 (、){ 、} 、?、 + 、等元字符元字符,使得正則表達式更加簡潔易用。

2.1.3 字符

在學習正則表達式前需要先學習字符。

  • POSIX 字符

通用 POSIX 原字符如下:

[:alnum:] 字母數字[a-z A-Z 0-9]
[:alpha:]	字母[a-z A-Z]
[:blank:]	空格或制表鍵
[:cntrl:] 任何控制字符
[:digit:] 數字 [0-9]
[:graph:] 任何可視字符(無空格)
[:lower:] 小寫 [a-z]
[:print:] 非控制字符	
[:punct:] 標點字符
[:space:] 空格
[:upper:] 大寫 [A-Z]
[:xdigit:] 十六進制數字 [0-9 a-f A-F]
  • 特殊字符

在擴展正則表達式中加上 \ 則被認為其具有特殊含義:

\w 匹配任意數字和字母,等效[a-zA-Z0-9_]
\W 和\w相反,等效[^a-zA-Z0-9_]
\b 匹配字符串開始或結束,等效\<和\>
\s 匹配任意的空白字符
\S 匹配非空白字符

2.1.4 區別

  • 基本正則表達元字符:只有 ^$.*[];
  • 擴展正則表達式元字符:^$.[]*+(){}?|;
  • 擴展正則表達式對于 {m,n} 和 () 不需要再向基本正則表達式需要 \ 來轉譯。

2.2 正則表達式操作

在 Linux 中正則表達式用來處理文本,在此我們使用 grep 工具對正則表達式進行操作,grep 為文本過濾工具,在 grep 命令中默認使用的時候基本正則表達式,可以使用選項 -E 來開啟擴展正則表達式,按照指定的正則表達式取出我們需求的內容。

2.2.1 字符匹配

在字符匹配前需要先學習。

  • .: 匹配任意單個字符,例如:
[root@master reg]# cat test.txt 
she
sh
s1e
[root@master reg]# grep "s.e" test.txt 
she
s1e

. 匹配必須為字母 s 與 e 中有任意單個字符。

  • [] : 匹配指定中括號范圍內的任意單個字符,例如:
[root@master reg]# cat test.txt 
she
sh
s1e
[root@master reg]# grep "s[a-z]e" test.txt 
she
[root@master reg]# grep "s[1-9]e" test.txt    
s1e
[root@master reg]# grep "s[[:alnum:]]e" test.txt      // 匹配字符或數字  
she
s1e
[root@master reg]# grep "s[[:alpha:]]e" test.txt    
she
[root@master reg]# grep "s[[:digit:]]e" test.txt      
s1e

中括號內可以利用元字符來表示。

[root@master reg]# cat test.txt 
she
sh
s1e
[root@master reg]# grep "s[^[:digit:]]e" test.txt    
she
[root@master reg]# grep "s[^a-z]e" test.txt          
s1e

如上,匹配的元字符取反,也就是不包含匹配的內容。

2.2.2 次數匹配

次數匹配用在指定的字符后面,表示指定匹配到前面的字符出現多少次。

  • *: 匹配前面的字符任意次(0 次或無數次),例如:
[root@master reg]# cat test2.txt 
ssssh
sheee
hell
[root@master reg]# grep "s*" test2.txt 
ssssh
sheee
hell	

如上匹配字符 s,0 次或多次。

  • \?: 匹配前面的字符 0 次或 1 次,例如:
[root@master reg]# cat test2.txt 
ssssh
sheee
hell
[root@master reg]# grep "s\?h" test2.txt 
ssssh						# 匹配最后的sh
sheee						# 匹配sh
hell						# 匹配h
[root@master reg]# grep -E "s?h" test2.txt  
ssssh
sheee
hell

如上匹配 s 可以存在 0 次,或者存在 1 次之后需要有 h 字符,注意利用選項 -E 開啟擴展正則表達式,相較于基本正則表達式不需要 \。

  • +: 匹配前面的字符至少 1 次,例如:
[root@master reg]# cat test2.txt 
ssssh
sheee
hell
[root@master reg]# grep "s\+h" test2.txt  
ssssh						# 匹配ssssh
sheee						# 匹配sh
[root@master reg]# grep -E "s+h" test2.txt
ssssh
sheee

如上匹配 s 至少存在 1 次或無數次。

  • \{m\,}: 匹配前面的字符至少 m 次(默認工作在貪婪模式下,? 取消貪婪模式),例如:
[root@master reg]# cat test2.txt 
ssssh
sheee
hell
[root@master reg]# grep "s\{1,\}" test2.txt 
ssssh
sheee
[root@master reg]# grep -E "s{1,}" test2.txt   
ssssh
sheee
[root@master reg]# grep "s\{2,\}" test2.txt  
ssssh
[root@master reg]# grep -E "s{2,}" test2.txt   
ssssh

匹配字符 s,最少 1 次。

  • \{,n}: 匹配前面的字符最多 n 次(默認工作在貪婪模式下,? 取消貪婪模式),例如:
[root@master reg]# cat test2.txt 
ssssh
sheee
hell
[root@master reg]# grep "s\{,2\}" test2.txt     
ssssh
sheee
hell
[root@master reg]# grep -E "s{,2}" test2.txt  
ssssh
sheee
hell

匹配字符 s,最多 2 次。

  • \{m,n\}: 匹配前面的字符至少 m 次,至多 n 次,例如:
[root@master reg]# cat test2.txt 
ssssh
sheee
hell
[root@master reg]# grep "s\{1,2\}" test2.txt    
ssssh
sheee
[root@master reg]# grep -E "s{1,2}" test2.txt 
ssssh
sheee

匹配字符 s,1-2 次之間。

  • .*: 匹配任意字符任意次數。

2.2.3 位置錨定

  • ^: 行首錨定,用于模式最左邊,例如:
[root@master reg]# cat test2.txt 
ssssh
sheee
hell
[root@master reg]# grep "^s" test2.txt 
ssssh
sheee

匹配以 s 開頭的行。

  • $: 行尾錨定,用于模式最右邊,例如:
[root@master reg]# cat test2.txt 
ssssh
sheee
hell
[root@master reg]# grep "h$" test2.txt 
ssssh

匹配以 h 結尾的行。

  • \<\b: 錨定詞首,用于單詞模式左側,例如:
[root@master reg]# cat test2.txt 
go root user
root:shell;gousers
hellorootgouser
[root@master reg]# grep "\<ro" test2.txt 
go root user
root:shell;gousers
[root@master reg]# grep "\bro" test2.txt         
go root user
root:shell;gousers

可以看到此刻匹配是以單詞模式,沒有匹配 helloroot。

  • \>\b: 錨定詞尾,用于單詞模式右側,例如:
[root@master reg]# grep "gouser\b" test2.txt 
hellorootgouser
[root@master reg]# grep "gouser\>" test2.txt  
hellorootgouser

2.2.4 分組引用

  • () 分組:將一個或多個字符當成一個整體來進行后續處理;
  • 1…數字引用:從左側起,引用第一個左括號以及與之匹配右括號之間的模式所匹配到的字符,后向引用,例如:
grep -E "(root).*\1" /etc/passwd

利用 () 將 root 引用起來,后面利用數字 1 引用。

3. 實例

1.顯示/etc/init.d/functions文件中以大小s開頭的行
grep '^[Pp]' /etc/init.d/functions

2.顯示/etc/passwd文件中以/bin/bash結尾的行
grep "/bin/bash$" /etc/passwd

3.顯示/etc/passwd文件中ID號最大用戶的用戶名
sort -t: -k3 -n /etc/passwd |tail -1 |cut -d: -f1

4.如果root用戶存在,顯示其默認的shell程序
id root && grep '^\<root\>' /etc/passwd |awk -F: '{print $NF}'

5.找出/etc/passwd中的兩位或三位數
grep -o "[0-9]\{2,3\}" /etc/passwd

6.顯示/etc/rc.d/rc.sysinit文件中,至少以一個空白字符開頭的且后面存非空白字符的行:
grep '^[[:space:]]\+[^[:space:]]' /etc/rc.d/rc.sysinit


7.找出"netstat -tan"命令的結果以"LISTEN"后跟0,1或多個空白字符結尾的行
netstat -tan|grep 'LISTEN[[:space:]]*$'

8.如果root用戶登錄了系統,就顯示root用戶在線,否則說明未登錄
w |grep '^\<root\>'>/dev/null && echo "root在線"|| echo "root未登錄"

9.找出/etc/rc.d/init.d/functions文件中某單詞后面跟一對小括號的行
grep '[[:alpha:]]*()' /etc/rc.d/init.d/functions

10.使用echo輸出一個路徑,使用egrep取出基名
echo /tmp/tmp1/vmstat.8.gz |grep -E  -o '[^/]+/?$'|cut -d/ -f1

11.匹配PPID開頭,行中又再次出現PPID的內容。/etc/init.d/functions
grep -E "(PPID).*\1" /etc/init.d/functions

12.利用awk找出/etc/ssh/sshd_config內出過空行與以#開頭的行
grep -v -E '^#|^$' /etc/ssh/sshd_config

4. 注意事項

  • 正則表達式中基本正則表達式與擴展正則表達式配合其它操作,能夠千變萬化,非常靈活,根據不同場景可以進行正向匹配和反向匹配;
  • 正則表達式配合命令通常為三劍客 grep/awk/sed 等,后期靈活進行組合達到事半功倍的效果;
  • 我們在文本模式匹配的時候可以考慮使用擴展的正則表達式,從而避免使用過多的轉義字符。

5 小結

正則表達式可謂 Shell 中的精華,其實在其他語言中也很通用,需要進行勤加練習才能達到熟練掌握,注意區分基本正則表達式與擴展正則表達式的語法區別,配合其他工具靈活運用。在不同場景可以利用命令選項配合使用,在后期 Shell 腳本三劍客中也會頻繁出現正則表達式,攻克正則表達式這個難關,Shell 腳本編程就已經事半功倍。