Perl學(xué)習(xí)筆記9——正則表達(dá)式(上)

正則表達(dá)式簡介

Perl最重要的一大特色就是對(duì)正則表達(dá)式的強(qiáng)力支持,這些支持提供了強(qiáng)大且靈活的字符串處理能力。正則表達(dá)式實(shí)質(zhì)上是Perl內(nèi)嵌的,自成一體的微型編程語言。其不只是Perl的一部分,在很多其他語言中也都有應(yīng)用。

Perl中,正則表達(dá)式通常簡稱為模式。正則表達(dá)式是具有一定特征的一個(gè)模板,任意的字符串都可以與其匹配,且只有兩種匹配結(jié)果:匹配或不匹配。所以正則表達(dá)式常用于布爾上下文中,從而使其匹配結(jié)果作為布爾值返回。

模式匹配操作符

Perl中,使用模式匹配操作符“m//”進(jìn)行模式匹配操作。完整的模式匹配操作符包括關(guān)鍵詞m其后的定界符。類似于qw簡寫,可以選用任意成對(duì)且合適的符號(hào)作為定界符,且當(dāng)以斜線作為定界符時(shí),可以省略關(guān)鍵字m。

當(dāng)沒有為m//指定匹配的內(nèi)容時(shí),其會(huì)默認(rèn)匹配$_的內(nèi)容。下例是一個(gè)簡單的模式匹配:

$_="abcd";

if(/a/){print'T'}else{print'F'}??? #模式/a/會(huì)在$_中匹配a,即$_中是否出現(xiàn)了a,結(jié)果是真,所以輸出T。由于以斜線作為定界符,所以省略了斜線前的m

模式中的內(nèi)插與反斜線轉(zhuǎn)義

所有在雙引號(hào)引起的字符串中可以使用的技巧,都可以在模式表達(dá)式中使用。最主要的即反斜線轉(zhuǎn)義和模式內(nèi)插。例:

print'T'if/\n/;??? #在模式中使用反斜線轉(zhuǎn)義,匹配換行符

print'T'if/$n/;??? #在模式中使用變量內(nèi)插,匹配$n的內(nèi)容

綁定操作符

默認(rèn)情況下m//的操作對(duì)象是$_的內(nèi)容。而如果要為模式指定匹配的對(duì)象,就可以使用綁定操作符“=~”。例:

print'T'if$n=~/a/;??? #模式用于匹配$n的內(nèi)容

綁定操作符是一個(gè)優(yōu)先級(jí)相當(dāng)高的操作符,所以在一般的表達(dá)式中,如果不使用括號(hào)限定,那么就會(huì)優(yōu)先進(jìn)行模式匹配。例:

$_=$n=~/a/;??? #先進(jìn)行匹配,再將匹配結(jié)果返回并賦值給$_(返回的結(jié)果為1或undef,默認(rèn)布爾值)

元字符初步

在模式中有一類特殊字符,一般情況下其不代表本身,而是有著特殊的含義,這一類字符就稱為元字符。在下文中會(huì)出現(xiàn)各種元字符的運(yùn)用。這里將常見的元字符列舉如下:

點(diǎn)號(hào)“.”

反斜線“\”

量詞“*”、“+”、“?”

小括號(hào)“( )”

中括號(hào)“[ ]”

豎線“|”

在模式中,點(diǎn)號(hào)又稱通配符,可以用于匹配任意一個(gè)非換行符字符。例:

/a../???? #可匹配aaa、abc等

/a..d/??? #可匹配abcd、aaad等

類似于雙引號(hào)圈引的字符串,在模式中反斜線可用于反斜線轉(zhuǎn)義,也可用于將特殊的元字符轉(zhuǎn)義為其自身。例:

/\n/???#匹配換行符

/\./???#匹配點(diǎn)號(hào)

/\\/???#匹配反斜線自身

量詞初步

在模式中,量詞可以用于重復(fù)量詞前的某一部分內(nèi)容。不同的量詞代表前面條目不同的的重復(fù)次數(shù)。常用的量詞主要有三種:星號(hào)“*”、加號(hào)“+”和問號(hào)“?”。星號(hào)量詞可以將其前面的條目重復(fù)零次至多次。也就是說,星號(hào)前面的條目可以不出現(xiàn),也可以重復(fù)出現(xiàn)任意多次。類似于星號(hào)量詞,加號(hào)量詞可以將其前面的條目重復(fù)一至多次。也就是說,加號(hào)前面的條目必須至少出現(xiàn)一次才能匹配。而問號(hào)量詞的限定更為嚴(yán)格,其前面的條目只能出現(xiàn)零次或一次才能匹配,其他情況均不能匹配。例:

/a*b/??? #可匹配b、ab、aaab等

/a+b/??? #可匹配ab、aaab等,但不能匹配b

/a?b/??? #可匹配b或ab

量詞很常見的用法就是與通配符連用,可以匹配多個(gè)任意字符。例:

/a.*b/??? #匹配a與b之間任意多個(gè)字符,可匹配ab、aaab等

/a.+b/??? #匹配a與b之間至少一個(gè)字符,可匹配a-b、aaab等,但不能匹配ab

/a.?b/??? #匹配a與b之間至多一個(gè)字符,可匹配ab、a-b等,但不能匹配abbb等

通用量詞

如果上文中的三個(gè)常用量詞都不符合需要,還可以使用通用量詞。通用量詞用于說明具體的重復(fù)次數(shù)范圍,其由一對(duì)花括號(hào)和其中的數(shù)字組成,數(shù)字可以為一個(gè)或兩個(gè),中間以逗號(hào)隔開,用以說明重復(fù)次數(shù)范圍。而如果省略第二個(gè)數(shù)字但有逗號(hào),則表示重復(fù)次數(shù)無上限。例:

/a{3}/???? ?#重復(fù)三次,只能匹配aaa

/a{3,5}/??? #可匹配重復(fù)次數(shù)三次至五次的a

/a{3,}/???? #可匹配重復(fù)至少三次的a

常用的三個(gè)量詞實(shí)質(zhì)上就是通用量詞的簡寫:

{0,}???? #相當(dāng)于*

{1,}???? #相當(dāng)于+

{0,1}??? #相當(dāng)于?

模式分組

在正則表達(dá)式中,小括號(hào)作為一種元字符,其作用為對(duì)模式表達(dá)式的內(nèi)容進(jìn)行分組,從而對(duì)這一組內(nèi)容進(jìn)行整體上的處理。最常見的如對(duì)一組內(nèi)容整體上使用量詞,而不是像上文那樣僅對(duì)量詞前的一個(gè)字符使用。模式分組實(shí)質(zhì)上是利用了小括號(hào)在模式中的最高優(yōu)先級(jí)這一性質(zhì)(詳見“優(yōu)先級(jí)”),從而使分組中的內(nèi)容形成一個(gè)整體,以實(shí)現(xiàn)各種整體上的操作。例:

/ab+/???? #量詞僅對(duì)其前面的b起作用,可匹配abbb等

/(ab)+/??? #使用模式分組,量詞對(duì)(ab)起作用,可匹配ababab等

擇一匹配

在正則表達(dá)式中,有一個(gè)類似于邏輯或操作符“||”的符號(hào)“|”,稱為擇一豎線,其可用于擇一匹配。擇一匹配的意思即擇一豎線兩邊的內(nèi)容都可以嘗試進(jìn)行匹配,也就是說,如果左邊的內(nèi)容匹配失敗,還可以嘗試匹配右邊的內(nèi)容。擇一豎線是模式匹配中優(yōu)先級(jí)最低的一個(gè)元字符,所以使用時(shí)應(yīng)注意在需要的時(shí)候使用模式分組。例:

/a|b|c/???? #匹配a或b或c

/a(b|c)d/??? #匹配abd或acd

/ab|cd/???? #匹配ab或cd

字符集

前文提到,一個(gè)點(diǎn)號(hào)可以用來代表任意一個(gè)非換行符字符。而如果需要匹配的可能字符種類沒有這么寬泛,而是一組特定的字符,比如需要匹配任意一個(gè)數(shù)字,或是小寫字母等,就可以使用字符集。

字符集書寫在一對(duì)方括號(hào)內(nèi),表示所有可能出現(xiàn)的字符。字符之間不需要任何分隔。例:

/[abc]/???? #一個(gè)字符集,可匹配abc中任意一個(gè)字符一次

/[123]+/??? #字符集與量詞連用,匹配123中任意一個(gè)字符至少一次

當(dāng)字符集內(nèi)的字符是一串連續(xù)字符時(shí),如26個(gè)小寫字母或0到9這十個(gè)數(shù)字等,就可以使用連字符表示始末范圍,這樣可以大大簡化字符集的書寫。例:

[0-9]????? #所有的數(shù)字構(gòu)成的字符集

[a-zA-Z]??? #所有的大小寫字母構(gòu)成的字符集

在字符集中,有時(shí)候還需要構(gòu)造反義字符集,即除了字符集中的字符,其他都匹配??梢栽谧址_頭的地方加上脫字符“^”來構(gòu)造反義字符集。例:

/[^0-9]/????? #匹配除了10個(gè)數(shù)字以外的字符一次

/[^a-zA-Z]/??? #匹配除了大小寫字母以外的字符一次

某些字符集的出現(xiàn)頻率非常高,所以Perl為其設(shè)定了簡寫。字符集簡寫均由反斜線后接一個(gè)字母組成。常用的字符集簡寫及其一般性解釋如下:

[\w]???#單詞字符集,一般相當(dāng)于[a-zA-Z0-9_],即所有大小寫字母加上10個(gè)數(shù)字和下劃線

[\d]???#數(shù)字字符集,一般相當(dāng)于[0-9]

[\s]???#空白符字符集,一般可匹配空格,換行符,制表符等空白符

簡寫的字符集也能構(gòu)造反義字符集,且無需使用脫字符,直接將小寫字母換成其對(duì)應(yīng)的大寫字母即可。例:

[\W]???[\D]??? [\S]??? #三種簡寫字符集的反義寫法

在不引起歧義的情況下,字符集的中括號(hào)??梢允÷?,從而簡化書寫。例:

/\w+/??? #簡寫的單詞字符集與量詞連用

模式匹配修飾符初步

Perl中提供了一系列模式匹配修飾符,又稱為副詞或標(biāo)志。其可以改變一些默認(rèn)的匹配行為,從而對(duì)模式匹配起到修飾的作用。模式匹配修飾符書寫在模式表達(dá)式末尾定界符的后面,其都是由一個(gè)字母構(gòu)成。下文列舉了一些常用的修飾符及其作用,還有其他的一些修飾符會(huì)在后文中陸續(xù)提及:

/i修飾符:可進(jìn)行大小寫無關(guān)的匹配,即模式表達(dá)式中的字母可匹配小寫也可匹配大寫。例:

/abc/i??? #進(jìn)行大小寫無關(guān)的匹配,可匹配abc、ABC、Abc等

/s修飾符:可增大通配符匹配范圍,使其能夠匹配到換行符,多用于含有多行的字符串匹配。例:

/a.*b/s??? #增大點(diǎn)號(hào)匹配范圍,使其能夠匹配到換行符??善ヅ?a\nb"等

/x修飾符:允許在模式中隨意加入空白符,使其更易閱讀和理解,多用于復(fù)雜模式中。也就是說,使用了/x修飾符后,就可以隨意在模式中加入空格或者換行符來分隔,而Perl會(huì)將其忽略。此時(shí)如果要表示換行符或者空格本身,可以使用反斜線轉(zhuǎn)義,或使用空白字符集[\s]來匹配空白符。例:

/a b/x?????????????? #在模式中忽略空格,相當(dāng)于/ab/

/a

b/x???????????????? #在模式中忽略換行符,相當(dāng)于/ab/

/a\ b/x??? /a\nb/x???#使用反斜線轉(zhuǎn)義表示空格和換行符本身

如果要在一個(gè)模式中使用多個(gè)修飾符,直接將多個(gè)修飾符一起寫在末尾定界符之后即可,先后順序不限。例:

/a b/isx??? #同時(shí)使用三個(gè)修飾符

模式替換操作符

正則表達(dá)式不僅可以用于匹配文本,還可以用于直接修改文本??梢允褂媚J教鎿Q操作符“s///”來對(duì)文本進(jìn)行匹配并修改。s///操作的字符串一般要求存儲(chǔ)于變量中,而實(shí)際上,如果對(duì)一個(gè)未存儲(chǔ)于變量中的字符串進(jìn)行修改,那么修改的結(jié)果也是不能夠存儲(chǔ)的,所以這樣做沒有實(shí)際意義。

與m//類似,s///由關(guān)鍵詞s及其后面的定界符構(gòu)成。第一對(duì)定界符內(nèi)為一個(gè)正則表達(dá)式,第二對(duì)定界符內(nèi)為用于替換的字符串。s///會(huì)先對(duì)給定字符串進(jìn)行模式匹配,如果匹配成功,就會(huì)將全部的匹配內(nèi)容替換成第二對(duì)定界符中的內(nèi)容,而如果匹配失敗,則不會(huì)有任何效果。s///在未綁定變量時(shí)默認(rèn)的操作對(duì)象也是$_中的內(nèi)容,可使用綁定操作符為其指定一個(gè)操作對(duì)象。例:

s/@/>/;??? #在$_中匹配@字符,如果匹配成功,則將其替換為>

與m//類似,s///中也可使用變量內(nèi)插、反斜線轉(zhuǎn)義等功能。在默認(rèn)情況下,s///只會(huì)對(duì)其匹配到的第一個(gè)可替換部分進(jìn)行替換,然后就結(jié)束語句。也就是說,即使還有其他可以替換的部分,在默認(rèn)情況下s///也只會(huì)進(jìn)行一次替換。例:

$_=aaa;

s/a/b/;??? #此時(shí)$_會(huì)被替換為baa

s///自身返回的是成功替換的次數(shù),在沒有修飾符的情況下,返回值只能為0或1,即成功替換的次數(shù)只能為0或1次。也可以將其返回值當(dāng)作布爾值使用,用來表示替換操作是否成功進(jìn)行。例:

print while s/a/b/;??? #將s///用在布爾上下文中,進(jìn)行循環(huán)替換

while(s/a/b/){}?????? #借助while循環(huán)進(jìn)行多次替換(僅作示例,實(shí)際上無需這種寫法,詳見“全局替換”)

上文提到,s///的關(guān)鍵詞s后面也是定界符,也就是說,s后面的符號(hào)可以任意選用。但由于s///后面的定界符不止一對(duì),所以使用上較m//有所區(qū)別。如果s///的定界符選用的是類似于斜線這樣的非成對(duì)字符,即沒有左右之分的定界符,那么用法就同斜線一樣,使用三個(gè)即可。而如果選用的定界符是類似于花括號(hào)這樣的分左右的成對(duì)字符,那么定界符就需要使用兩對(duì),一對(duì)包住模式,另一對(duì)包住替換字符串。且在這種使用兩對(duì)定界符的情況下,這兩對(duì)定界符可以分別選用不同的符號(hào),可以成對(duì),也可以非成對(duì)。依據(jù)需求選用即可。例:

s#a#b#;??? #使用非成對(duì)字符井號(hào)作為定界符

s{a};???? #使用成對(duì)的花括號(hào)作為定界符

s\b\;? ? ? ? ?#定界符混合使用

s/a/b/;???? #上面的三個(gè)語句都和此寫法沒有任何區(qū)別

全局替換

上文提到,在默認(rèn)情況下,s///最多只能進(jìn)行一次替換。而如果想讓s///進(jìn)行全部可能的替換,就可以使用全局替換修飾符“/g”。

/g修飾符可以讓s///進(jìn)行所有可能且不重復(fù)的替換,這里的不重復(fù)是指:s///的每一次模式匹配都會(huì)從最近一次替換操作結(jié)束位點(diǎn)的下一個(gè)字符開始,從而避免對(duì)已被替換的內(nèi)容進(jìn)行重復(fù)替換。例:

s/a/b/g;??? #對(duì)$_進(jìn)行全局替換,將所有匹配到的a替換為b

s///的修飾符用法和m//一致,都可以同時(shí)使用多個(gè)修飾符,且直接將多個(gè)修飾符一起寫在s///的最后一個(gè)定界符之后即可,順序不限。例:

s/a/b/gix;??? #同時(shí)使用三個(gè)修飾符

無損替換

上文提到,在默認(rèn)情況下,s///會(huì)直接修改變量的內(nèi)容,而其自身返回的是成功替換的次數(shù)。而如果需要保留原字符串的內(nèi)容,且將替換后的結(jié)果作為s///的返回值返回,就可以使用無損替換修飾符“/r”。

/r修飾符可以讓s///的返回值由成功替換的次數(shù)變?yōu)樘鎿Q結(jié)果,并且不對(duì)原字符串的內(nèi)容做任何修改,從而實(shí)現(xiàn)無損替換。例:

$n=s/a/b/gr;??? #對(duì)$_進(jìn)行無損的全局替換,并將結(jié)果返回并賦值給$n,$_中的內(nèi)容不會(huì)改變


櫻雨樓

完成于2016.1.19

最后修改于2016.2.1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 捕獲組與反向引用 在正則表達(dá)式中,圓括號(hào)的一大作用是進(jìn)行模式分組,而其還有另一個(gè)非常重要的作用,即定義捕獲組。捕獲...
    櫻雨樓閱讀 1,843評(píng)論 0 0
  • Python中的正則表達(dá)式(re) import rere.match #從開始位置開始匹配,如果開頭沒有則無re...
    BigJeffWang閱讀 7,595評(píng)論 0 99
  • 從匹配中返回值 Match 對(duì)象 成功的匹配總是返回一個(gè) Match 對(duì)象, 這個(gè)對(duì)象通常也被放進(jìn) $/ 中, (...
    焉知非魚閱讀 1,937評(píng)論 0 1
  • 官網(wǎng) 中文版本 好的網(wǎng)站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,717評(píng)論 0 5
  • 初衷:看了很多視頻、文章,最后卻通通忘記了,別人的知識(shí)依舊是別人的,自己卻什么都沒獲得。此系列文章旨在加深自己的印...
    DCbryant閱讀 4,257評(píng)論 0 20

友情鏈接更多精彩內(nèi)容