Linux命令行與Shell腳本編程 第十九章 正則表達(dá)式
九.正則表達(dá)式
- 正則表達(dá)式基礎(chǔ)
- 定義BRE模式
- 擴(kuò)展正則表達(dá)式
在sed和gawk中創(chuàng)建正則表達(dá)式,以得到所需的數(shù)據(jù)。
9.1.正則表達(dá)式基礎(chǔ)
正則表達(dá)式是一種可供Linux工具過濾文本的自定義模板,使用元字符來描述數(shù)據(jù)流中的一個(gè)或多個(gè)字符.
Linux工具(比如sed或gawk)會(huì)在讀取數(shù)據(jù)時(shí)使用正則表達(dá)式對(duì)數(shù)據(jù)進(jìn)行模式匹配。如果數(shù)據(jù)匹配模式,它就會(huì)被接受并進(jìn)行處理。
正則表達(dá)式包含文本和/或特殊字符.
9.1.1.正則表達(dá)式的類型
不同的應(yīng)用程序可能使用不同類型的正則表達(dá)式。
編程語言(Java、Python)、Linux工具(sed、gawk和grep)以及主流應(yīng)用程序(MySQL數(shù)據(jù)庫服務(wù)器)。
正則表達(dá)式由正則表達(dá)式引擎實(shí)現(xiàn)。這種底層軟件,負(fù)責(zé)解釋正則表達(dá)式并用這些模式進(jìn)行文本匹配。
Linux 中流行的兩種:
- POSIX基礎(chǔ)正則表達(dá)式(basic regular expression,BRE)引擎。
- POSIX擴(kuò)展正則表達(dá)式(extended regular expression,ERE)引擎。
大多數(shù)Linux工具至少符合POSIX BRE引擎規(guī)范。但有些工具(比如sed)僅符合BRE引擎規(guī)范的一個(gè)子集。
(出于速度方面的考慮導(dǎo)致,sed希望盡可能快地處理數(shù)據(jù)流中的文本)
POSIX ERE引擎多見于依賴正則表達(dá)式過濾文本的編程語言中。為常見模式(比如數(shù)字、單詞以及字母或數(shù)字字符)提供了高級(jí)模式符號(hào)和特殊符號(hào)。
gawk就是使用ERE引擎來處理正則表達(dá)式。
9.2.定義BRE模式
最基本的BRE模式是匹配數(shù)據(jù)流中的文本字符.
9.2.1.普通文本
正則表達(dá)式對(duì)大小寫敏感.
正則表達(dá)式并不關(guān)心模式在數(shù)據(jù)流中出現(xiàn)的位置,也不在意模式出現(xiàn)了多少次。
只要能匹配文本字符串中任意位置的模式,正則表達(dá)式就會(huì)將該字符串傳回Linux工具。
在正則表達(dá)式中,空格和其他的字符沒有區(qū)別.如果在正則表達(dá)式中定義了空格,那么必須出現(xiàn)在數(shù)據(jù)流中。甚至可以創(chuàng)建匹配多個(gè)連續(xù)空格的正則表達(dá)式.
$ cat data1
This is a normal line of text.
This is a line with too many spaces.
$ sed -n '/ /p' data1
This is a line with too many spaces.
9.2.2.特殊字符
正則表達(dá)式中的一些字符具有特別的含義:
- .
- *
- []
- ^
- $
- {}
- \
- +
- ?
- |
- ()
不能在匹配普通文本的模式中單獨(dú)使用這些字符.
如果要將某個(gè)特殊字符視為普通字符,則必須將其轉(zhuǎn)義.使用特殊轉(zhuǎn)移字符反斜線(\)。
盡管正斜線 / 不屬于正則表達(dá)式的特殊字符,但如果出現(xiàn)在sed或gawk的正則表達(dá)式中,就會(huì)出現(xiàn)錯(cuò)誤,所以正斜線也需要進(jìn)行轉(zhuǎn)義.
9.2.3.錨點(diǎn)字符
默認(rèn)情況下,當(dāng)指定一個(gè)正則表達(dá)式模式時(shí),只要模式出現(xiàn)在數(shù)據(jù)流中的任何地方,它就能匹配.有兩個(gè)特殊字符可以用來將模式鎖定在數(shù)據(jù)流中的行首或行尾。
錨定行首^
脫字符(^)可以指定位于數(shù)據(jù)流中文本行行首的模式。如果模式出現(xiàn)在行首之外的位置,則正則表達(dá)式無法匹配。
使用脫字符,就必須將其置于正則表達(dá)式之前
$ echo "The book store" | sed -n '/^book/p'
$
$ echo "Books are great" | sed -n '/^Book/p'
Books are great
如果將脫字符放到正則表達(dá)式開頭之外的位置,那么就跟普通字符一樣,沒有特殊含義
$ echo "This ^ is a test" | sed -n '/s ^/p'
This ^ is a test
如果正則表達(dá)式模式中只有脫字符,就不必用反斜線來轉(zhuǎn)義。但如果在正則表達(dá)式中先指定脫字符,隨后還有其他文本,就必須在脫字符前用轉(zhuǎn)義字符.
$ echo "This is ^ a test" | sed -n '/^ a test/p'
$ echo "This is ^ a test" | sed -n '/\^ a test/p'
This is ^ a test
錨定行尾$
與在行首查找模式相反的情況是在行尾查找。特殊字符美元符號(hào)($)定義了行尾錨點(diǎn)。將這個(gè)特殊字符放在正則表達(dá)式之后則表示數(shù)據(jù)行必須以該模式結(jié)尾.
$ echo "This is a good book" | sed -n '/book$/p'
This is a good book
組合錨點(diǎn)
組合使用行首錨點(diǎn)和行尾錨點(diǎn)。
$ cat data4
this is a test of using both anchors
I said this is a test
this is a test
I'm sure this is a test.
$ sed -n '/^this is a test$/p' data4
this is a test
將這兩個(gè)錨點(diǎn)直接組合,之間不加任何文本,可以過濾掉數(shù)據(jù)流中的空行。
組合 刪除命令d就可以刪除掉文本中的空行.
$ cat data5
This is one test line.
This is another test line.
$ sed '/^$/d' data5
This is one test line.
This is another test line.
9.2.4.點(diǎn)號(hào)字符.
點(diǎn)號(hào)字符可以匹配除換行符之外的任意單個(gè)字符。(空格也是字符,可以匹配)
點(diǎn)號(hào)字符必須匹配一個(gè)字符,如果在點(diǎn)號(hào)字符的位置沒有可匹配的字符,那么模式不成立。
$ cat data6
This is a test of a line.
The cat is sleeping.
That is a very nice hat.
This test is at line four.
at ten o'clock we'll go home.
$ sed -n '/.at/p' data6
The cat is sleeping.
That is a very nice hat.
This test is at line four.
9.2.5.字符組[]
想要限定要匹配的具體字符使用字符組.
可以在正則表達(dá)式中定義用來匹配某個(gè)位置的一組字符。如果字符組中的某個(gè)字符出現(xiàn)在了數(shù)據(jù)流中,那就能匹配該模式。
方括號(hào) [] 用于定義字符組。
在不太確定某個(gè)字符的大小寫時(shí)非常適合使用字符組.
$ echo "Yes" | sed -n '/[Yy]es/p'
Yes
$ echo "yes" | sed -n '/[Yy]es/p'
yes
在一個(gè)正則表達(dá)式中可以使用多個(gè)字符組.
可以將多個(gè)字符組組合在一起,以檢查數(shù)字是否具備正確的格式.
$ cat data8
60633
46201
223001
4353
22203
$ sed -n '
> /^[0123456789][0123456789][0123456789][0123456789][0123456789]$/p
> ' data8
60633
46201
22203
9.2.6.排除字符組
在正則表達(dá)式中,可以反轉(zhuǎn)字符組的作用:匹配字符組中沒有的字符。在字符組的開頭添加脫字符^:
$ sed -n '/[^ch]at/p' data6
This test is at line four.
即使是排除型,字符組仍必須匹配一個(gè)字符,以at為起始的行還是不能匹配模式!!!
8.2.7.區(qū)間
可以用單連字符在字符組中表示字符區(qū)間。只需指定區(qū)間的第一個(gè)字符、連字符以及區(qū)間的最后一個(gè)字符。
根據(jù)Linux系統(tǒng)使用的字符集,字符組會(huì)包括在此區(qū)間內(nèi)的任意字符。
$ sed -n '/^[0-9][0-9][0-9][0-9][0-9]$/p' data8
60633
46201
45902
同樣的方法也適用于字母:
$ sed -n '/[c-h]at/p' data6
The cat is sleeping.
That is a very nice hat.
可以在單個(gè)字符組內(nèi)指定多個(gè)不連續(xù)的區(qū)間:
$ sed -n '/[a-ch-m]at/p' data6
The cat is sleeping.
That is a very nice hat.
9.2.8.特殊字符組
BRE還提供了一些特殊的字符組,用來匹配特定類型的字符。
字符組 | 描述 |
---|---|
[[:alpha:]] | 匹配任意字母字符,無論大小寫 |
[[:alnum:]] | 匹配任意字母和數(shù)組字符,0-9、a-z、A-Z |
[[:blank:]] | 匹配空格和制表符 |
[[:digit:]] | 匹配0-9的數(shù)字 |
[[:lower:]] | 匹配a-z的字母 |
[[:upper:]] | 匹配A-Z的字母 |
[[:print:]] | 匹配任意可打印字符 |
[[:punct:]] | 匹配標(biāo)點(diǎn)符號(hào) |
[[:space:]] | 匹配任意空白字符:空格、制表符、換行符、分頁符、垂直制表符、回車符 |
特殊字符組在正則表達(dá)式中的用法和普通字符組一樣:
$ echo "abc" | sed -n '/[[:digit:]]/p'
$ echo "abc" | sed -n '/[[:alpha:]]/p'
abc
$ echo "abc123" | sed -n '/[[:digit:]]/p'
abc123
$ echo "This is a test" | sed -n '/[[:punct:]]/p'
$ echo "This is, a test" | sed -n '/[[:punct:]]/p'
This is, a test
9.2.9.星號(hào)*
在字符后面放置星號(hào),表明該字符必須在匹配模式的文本中出現(xiàn)0次或多次.
$ echo "ik" | sed -n '/ie*k/p'
ik
$ echo "iek" | sed -n '/ie*k/p'
iek
$ echo "ieek" | sed -n '/ie*k/p'
ieek
$ echo "ieeek" | sed -n '/ie*k/p'
ieeek
$ echo "ieeeek" | sed -n '/ie*k/p'
ieeeek
某些單詞在英美中不同,借助 星號(hào)可以匹配:
$ echo "I'm getting a color TV" | sed -n '/colou*r/p'
I'm getting a color TV
$ echo "I'm getting a colour TV" | sed -n '/colou*r/p'
I'm getting a colour TV
$
將點(diǎn)號(hào)字符和星號(hào)字符組合起來。這個(gè)組合能夠匹配任意數(shù)量的任意字符:
$ echo "this is a regular pattern expression" | sed -n '
> /regular.*expression/p'
this is a regular pattern expression
星號(hào)用于字符組時(shí),指定可能在文本中出現(xiàn)0次或多次的字符組或字符區(qū)間:
$ echo "bt" | sed -n '/b[ae]*t/p'
bt
baaeeet
$ echo "baeeaeeat" | sed -n '/b[ae]*t/p'
baeeaeeat
$ echo "baakeeet" | sed -n '/b[ae]*t/p'
9.3.擴(kuò)展正則表達(dá)式
POSIX ERE模式提供了一些可供Linux應(yīng)用程序和工具使用的額外符號(hào)。gawk支持ERE模式,sed不支持。
可用于gawk腳本中的常見ERE模式符號(hào)。
9.3.1.問號(hào)?
問號(hào)表明字符可以出現(xiàn)0次或1次,不會(huì)匹配多次出現(xiàn)的該字符.用法與星號(hào)類似,可以作用與字符組.
$ echo "bt" | gawk '/be?t/{print $0}'
bt
$ echo "bet" | gawk '/be?t/{print $0}'
bet
$ echo "beet" | gawk '/be?t/{print $0}'
9.3.2.加號(hào)+
加號(hào)表明前面的字符可以出現(xiàn)1次或多次,必須至少出現(xiàn)1次。用法與星號(hào)類似,可以作用與字符組.
$ echo "bt" | gawk '/b[ae]+t/{print $0}'
$
$ echo "bat" | gawk '/b[ae]+t/{print $0}'
bat
$ echo "bet" | gawk '/b[ae]+t/{print $0}'
bet
$ echo "beat" | gawk '/b[ae]+t/{print $0}'
beat
$ echo "beet" | gawk '/b[ae]+t/{print $0}'
beet
$ echo "beeat" | gawk '/b[ae]+t/{print $0}'
beeat
9.3.3.花括號(hào){}
ERE中的花括號(hào)允許為正則表達(dá)式指定具體的可重復(fù)次數(shù),稱為區(qū)間。
可以用兩種格式來指定區(qū)間:
- m:正則表達(dá)式恰好出現(xiàn)m次。
- m, n:正則表達(dá)式至少出現(xiàn)m次,至多出現(xiàn)n次。
默認(rèn)情況下,gawk也不識(shí)別正則表達(dá)式區(qū)間,必須指定gawk的命令行選項(xiàng)–re-interval。
$ echo "bt" | gawk --re-interval '/be{1}t/{print $0}'
$
$ echo "bet" | gawk --re-interval '/be{1}t/{print $0}'
bet
$ echo "beet" | gawk --re-interval '/be{1}t/{print $0}'
$
$ echo "bt" | gawk --re-interval '/be{1,2}t/{print $0}'
$
$ echo "bet" | gawk --re-interval '/be{1,2}t/{print $0}'
bet
$ echo "beet" | gawk --re-interval '/be{1,2}t/{print $0}'
beet
$ echo "beeet" | gawk --re-interval '/be{1,2}t/{print $0}'
$
$ echo "bt" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
$
$ echo "beet" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
beet
$ echo "beeat" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
$
9.3.4.豎線符號(hào)|
豎線符號(hào)允許在檢查數(shù)據(jù)流時(shí),以邏輯OR方式指定正則表達(dá)式引擎要使用的兩個(gè)或多個(gè)模式。任何一個(gè)模式匹配了數(shù)據(jù)流文本,就視為匹配。
豎線符號(hào)兩側(cè)的子表達(dá)式可以采用正則表達(dá)式可用的任何模式符號(hào)(包括字符組)
$ echo "The cat is asleep" | gawk '/cat|dog/{print $0}'
The cat is asleep
$ echo "The dog is asleep" | gawk '/cat|dog/{print $0}'
The dog is asleep
$ echo "The sheep is asleep" | gawk '/cat|dog/{print $0}'
9.3.5.表達(dá)式分組
用圓括號(hào)對(duì)正則表達(dá)式進(jìn)行分組。分組之后,每一組會(huì)被視為一個(gè)整體,可以像對(duì)普通字符一樣對(duì)該組應(yīng)用特殊字符。
$ echo "Sat" | gawk '/Sat(urday)+/{print $0}'
$ echo "Saturday" | gawk '/Sat(urday)+/{print $0}'
Saturday
將分組和豎線符號(hào)結(jié)合起來創(chuàng)建可選的模式匹配組:
$ echo "cat" | gawk '/(c|b)a(b|t)/{print $0}'
cat
$ echo "cab" | gawk '/(c|b)a(b|t)/{print $0}'
cab
$ echo "bat" | gawk '/(c|b)a(b|t)/{print $0}'
bat
$ echo "bab" | gawk '/(c|b)a(b|t)/{print $0}'
bab
$ echo "tab" | gawk '/(c|b)a(b|t)/{print $0}'
$
9.4.實(shí)戰(zhàn)
9.4.1.目錄文件計(jì)數(shù)
對(duì)PATH環(huán)境變量中各個(gè)目錄所包含的文件數(shù)量進(jìn)行統(tǒng)計(jì).
PATH中的各個(gè)路徑由冒號(hào)分隔。要獲取可在腳本中使用的目錄列表,須用空格替換冒號(hào).
$ echo $PATH | sed 's/:/ /g'
/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin
/usr/games /usr/local/games
分離出目錄之后,可以使用標(biāo)準(zhǔn)for語句遍歷每個(gè)目錄:
mypath=`echo $PATH | sed 's/:/ /g'`
for directory in $mypath
do
...
done
對(duì)于單個(gè)目錄,可以用ls命令列出其中的文件,再用另一個(gè)for語句來遍歷每個(gè)文件,對(duì)文件計(jì)數(shù)器增值。文章來源:http://www.zghlxwxcb.cn/news/detail-646216.html
$ cat countfiles
#!/bin/bash
# count number of files in your PATH
mypath=$(echo $PATH | sed 's/:/ /g')
count=0
for directory in $mypath
do
check=$(ls $directory)
for item in $check
do
count=$[ $count + 1 ]
done
echo "$directory - $count"
count=0
done
$ ./countfiles /usr/local/sbin - 0
/usr/local/bin - 2
/usr/sbin - 213
/usr/bin - 1427
...
/usr/local/games - 0
文章來源地址http://www.zghlxwxcb.cn/news/detail-646216.html
到了這里,關(guān)于【Linux命令行與Shell腳本編程】第十九章 正則表達(dá)式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!