perlRegex第二周筆記

來源:互聯網
上載者:User

標籤:

1.使用Regex修改文本 1.使用Regex修改文本

Regex的功能不只有查詢,還可以對文本進行修改,例如替換

$var=~m/regex/i                             
$var=~s/regex/replacement/i

Replacement兩側的斜杠相當於雙引號,也就是說replacement中可以有$1,$2這樣的變數來代表前面匹配到的內容
$var=~s/regex/replacement/可以改變$var中的文本,如果沒有匹配成功,就不會有文本的替換

$var=Jeff frield;
$var=~s/Jeff/Jeffery/;
$var=Jeffery frield

可是如果在運行$var=~s/Jeff/Jeffery/一次,就會得到:

$var=Jefferyery fried;

因為Jeff始終被匹配,所以替換始終會發生。
要避免這樣的情況,我們必須要把匹配條件說的再具體一些。
匹配的是Jeff這個單詞,而不是這四個字母,所以我們用:

$var=~s/\bJeff\b/Jeffery/

這樣子第二次運行$var=~s/\bJeff\b/Jeffery/就不會再改變文本了

1.1例子一公函產生器

設想有一個公函系統,它包含很多公函魔板,其中一些標記,對每一封具體的公函來說,標記部分的值都有所不同
例如:
尊敬的=FIRST=,
恭喜您!獲得了=TRINKET=!完全免費!您還想為=FAMILY=家獲得更多的=TRINKEY=嗎?告訴你=FULL=,你可以的!

然後設定三個變數:

$given="王";
$family="小明";
$prize="10000克拉的鑽石";

然後我們就可以為語句的模板填寫內容:

$letter=~s/=FIRST=/$family/g;
$letter=~s/=FAMILY=/$given/g;
$letter=~s/=FULL=/$given $family/g;
$letter=~s/=TRINKET=/價值連城$prize/g;

g是全域替換的修飾符,他告訴s///在一次匹配替換成功以後繼續下一次,直到匹配不成功為止,從而達到全部相關文本都被替換的效果
結果:
尊敬的 小明,
恭喜您!獲得了 價值連城10000克拉的鑽石!完全免費!您還想為王家獲得更多的價值連城10000克拉的鑽石嗎?告訴你王小明,你可以的!

1.2 例子二修整數字格式

有時候因為電腦內部表示浮點的原理,輸出來的數字是9.05000000372272,可是我們其實只需要保留小數點後三位就可以了
要求就是:保留小數點後兩位,如果第三位不為0,也要保留,例如12.3750000000392會變成12.375,37.500會變成37.50.

$num=~s/(\.\d\d[1-9]?)\d*/$1/;

用環視功能為數值添加逗號
大的數值,為了方便讀懂,通常在其間加入逗號。

Print "the US population is $pop\n";

會輸出the US population is 298444215,但298,444,215會更加順眼。

我們應該從數位右邊開始,每次數三個數字如果左邊還有數字,就加入一個逗號。
這是直觀的想法,但是Regex是從左至右去處理文本的。
逗號應該加在”左邊有數字,右邊數位個數正好是3的倍數的位置“。
對於這樣的任務,我們用環視功能來實現。
環視結構不匹配任何字元,只匹配文本中特定的位置。這個特性其實我們前面已經見過很多次,例如\b、^、$等,都是匹配一個位置,但環視比它們更加通用,因為它匹配的位置是你自己定義的。

順序環視:從左至右查看文本,嘗試匹配Regex。肯定型順序環視用(?=……)來表示,例如(?=\d),表示如果當前位置右邊的字元是數字則匹配成功
逆序環視:從右至左查看文本,嘗試匹配Regex。肯定型逆序環視用(?<=……)來表示,例如(?<=\d),表示如果當前位置左邊字元是數字則匹配成功(也就是緊跟在數字後面的位置)。

環視Regex在匹配的時候不會“佔用”字元,只是匹配位置。
用Jeffery匹配by Jeffery friedl,匹配到是Jeffery這幾個字元之前的位置

把環視結構和真正匹配的字元結合起來使用,我們能匹配到更加精準的內容,例如:
(?=Jeffery)Jeff
能匹配到by Jeffery friedl
不能匹配by Jefferson

(?=Jeffery)Jeff ;Jeff(?=ery)
Jeff(?=Jeffery)不能夠匹配以上例子,而是匹配後面緊跟Jeffery的Jeff,例如JeffJeffery

1.3例子三effs=》Jeff’s

把Jeffs換成Jeff’s

s/Jeffs/Jeff’s/
s/\bJeffs\b/Jeff’ s/
s/\b(Jeff)(s)\b/$1’$2/
s/\bJeff(?=s\b)/Jeff’/

環視只是匹配一個位置,它的好處是容許我們在匹配Jeff前先檢查整個Jeffs

s/(?<=\bJeff)(?=s\b)/’/
s/(?=s\b)(?<=\bJeff)/’/

用順序環視和逆序環視找到了一個精確的位置,因為找的只是位置,所以條件循序調換了也沒有影響。

1.4例子四回到逗號

“左邊有數字,右邊數位個數正好是3的倍數”。
第一個要求用逆序環視就能夠滿足,左邊有數字,(?<=\d)
第二個要求:3位元字可以表示成\d\d\d,然後可以用(\d\d\d)+表示3的若干倍
最後再加上$來確保這些數字後面不存在其他字元,以保證這樣的結果“正好”在最後3位元字之後結束

$pop=~s/(?<=\d)(?=(\d\d\d)+$)/,/g;
Print"The US population is $pop\n";

298,444,215

試想,如果不加$,會有什麼後果?

$pop=~s/(?<=\d)(?=(\d\d\d)+)/,/g;

2,9,8,4,4,4,215
而且這裡括住\d\d\d的括弧,其實我們只是用來使得+可以作用於這個括弧,並沒有使用它的捕獲功能,所以可以寫成非捕獲型括弧:(?:......)

$pop=~s/(?<=\d)(?=(?:\d\d\d)+$)/,/g;

否定環視
現在,我們又希望把這個插入逗號的Regex應用到很長的字串匯中,例如

$text="The population of 299444215 is growing"

這樣子s/(?<=\d)(?=(\d\d\d)+$)/,/g;就不管用了,因為數字之後不是結尾,所以匹配不成功
解決方案:可以把$換成\b,儘管\b被稱為單詞分隔字元,但是對於perl來說,匹配單詞的\w是[a-zA-Z0-9],把數字也包括進去了,所以這是廣義的單詞
注意到這裡,\b的意思就是,在此位置的一側是單詞,另外一側不是

環視也有相關的概念,前面我們說的(?=)(?<=)都叫做肯定順序環視和肯定逆序環視。因為他們成功的條件是子運算式在這些位置能夠匹配
另外還有否定順序環視(?!)和否定逆序環視(?<!),他們成功條件是子運算式無法匹配

類型 Regex 匹配成功的條件
肯定順序環視 (?=) 子運算式能夠匹配右側文本
肯定逆序環視 (?<=) 子運算式能夠匹配左側文本
否定順序環視 (?!) 子運算式不能夠匹配右側文本
否定逆序環視 (? 子運算式不能夠匹配左側文本

這樣,其實\b就是(?<!\w)(?=\w)|(?<=\w)(?!\w)

s/(?<=\d)(?=(\d\d\d)+(?!\d)/,/g;

不是所有的宿主語言都支援逆序環視
那麼我們可以這樣子寫,這樣就沒有用到逆序環視

s/(\d)(?=(\d\d\d)+$)/$1,/g;

如果連順序環視都不用呢?

s/(\d)((\d\d\d)+\b)/$1,$2/g;

可以嗎?

答案是不可以,結果是298,444215
因為g這個修飾符規定,下一次匹配是在這一次匹配的終點開始的。但是在第一次匹配時,(\d\d\d)+\b已經匹配了444215,所以g的下一次匹配開始是在5的後面
解決方案是在perl中加個while迴圈,重複匹配,而不是迭代匹配

2.Regex使用注意事項

在某種特定的宿主語言或工具軟體中使用Regex時,主要有3個問題需要注意
1.支援的元字元,以及這些元字元的意義,這通常稱為Regex的“流派”
2.Regex與語言工具的“互動方式”。譬如如何進行Regex的操作,容許進行哪些操作,以及這些操作的目標文本類型
3.Regex引擎如何將運算式應用到文本

由於Regex的漫長的發展史,眾多程式員,新的程式又形成自己的流派,所以就成了巨大的迷局。
直到1986年,POSIX(一系列標準)誕生,它是標準化的嘗試,試圖把纏繞不清的Regex各個流派標準化,用同一套規則來實現Regex。它把各種常見的流派分為兩大類:
Basic Regular Expressions(BREs)和Extended Regular Expressions(EREs)
POSIX程式必須支援其中任意一種

perlRegex第二周筆記

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.