正規表達式總複習| Regular Expression Summary - Medium

文章推薦指數: 80 %
投票人數:10人

總之,今天要來講的是「正規表達法(Regular Expression)」。

話不多說,讓我們趕緊 ... 給123ab456cd789 則會挑出123 和456,但不包含後面的英文字 GetunlimitedaccessOpeninappHomeNotificationsListsStoriesWritePublishedin狗奴工程師正規表達式總複習|RegularExpressionSummary前言時至今日,我們的生活中會需要填許許多多的表單(form),例如調查大型聚會的時間。

從茫茫資料海當中,我們必須擷取出有用的數據來作分析,以此改善產品的品質或將資料作一層轉換。

對於這些步驟,光用if-else來做肯定會累死人且不實際,所以「正規表達法」就隨著這些需求而誕生。

總之,今天要來講的是「正規表達法(RegularExpression)」。

話不多說,讓我們趕緊開始吧!CharacterClasses(字元集合)原則上我們會需要明確指定出要比對的字元,例如英文字母A或數字1。

但更多時候我們要比對的字元會介於一個範圍內,所以正規表達法也有規定一些通用的keyword來代表一些字元。

\s:空白字元(包含tabs)\d:數字(即0–9)\w:數字+英文字母+底線符號(_).:任意字元Anchors(錨點、定位符號)錨點的作用是「定位」。

也就是這些符號並不會被用於「比對」,而是用來規定一些特定的字串必須待在指定的位置,例如開頭與結尾。

^(startwith):開頭有XXX的字串$(endwith):結尾有XXX的字串\b(boundary):表示特定位置不可有wordcharacter(\w)\A(absolutelystartwith):類似^但差別在於不受multi-linemode影響,一律把整個輸入當作一個字串。

\Z(multi-lineendwith):類似%但差別是不受multi-linemode影響,一律將輸入視作一個字串,而且允許結尾有多餘的換行(trailingnewline)。

\z(absolutelymulti-lineendwith):同上,但不允許有多餘的換行\b這個定位符號,可以用在比對字詞(word),其中一邊會是\w中的字元,而另外一邊則必須不是\w中的字元才會符合此表達式。

舉個例子來說:+abc+、abc、abcdef都符合\babc\b。

其中+abc+會符合的原因是+並不是\w中定義的wordcharacter,所以可以被接受。

後面的三個定位符號很少在使用,我也是在查找資料才知道有這些符號可以使用,因為沒特別使用到multi-linemode也就不太會注意到這個細節。

如果對\Z與\z還是分不清楚,可以用下面的這些例子來釐清:(O)foo~=foo\Z(O)foo~=foo\z(O)foo\n~=foo\Z(X)foo\n~=foo\z如果硬要背的話,感覺用「z比較小心眼」也許不錯,畢竟z是小寫😄Quantifiers(數詞符號)數詞用於規範特定字串會重複的次數。

?:字串在比對時可有可無(但至多一次)+:字串必須出現至少一次(可無限多次)*:字串可出現任意次數{a,b}:字串出現的次數必須介於a和b之間(b前面不能有空格)OROperators正規表達式沒有特別使用oroperator的時候都是「sequentialmatching」,也就是表達式中的字串都有可能同時存在。

但當使用oroperator時就變成唯有其一可以存在。

|:用於二個字元以上的字串,例如hello|hi|hey[]:用於單一字元的字串,例如[abc]代表a、b或c都可事實上[]還有其他用法,例如說當字元是「數字」或「字母」,而且剛好是連續的,那可以用-來簡化表達式。

像是[abcdefgh]其實就可以簡化成[a-h]。

值得注意的是,一般使用「|」會搭配groupcapturing,以確保不會搞錯語意。

例如:abc(def|ghi)與abcdef|ghi所表達的是不同的意思。

abc(def|ghi):abc後面接著def或ghiabcdef|ghi:abcdef或ghi因此我們很高機率會使用group的形式來確保語意的正確性,這會間接導致後續擷取group的值時需要注意group的順序。

對於這項問題,晚點介紹group時會一併提及該如何解決。

Negation否定詞有時候我們想比對的目標字串(pattern)範圍很廣,比如說:挑出不含有a,t,i,w的字串,或是挑出不含有數字的字串。

這個時候以前所學到的來撰寫,那你的正規表達式就會變得很長且不易閱讀。

因此,語法中也提供一些「否定語法(negation)」讓開發者可以解決上述的問題。

定位符號與字元集合有些定位符號(anchors)與字元集合(characterclasses)有其否定語法,都只需要把英文改成大寫就可以。

清單如下:\W:不是wordcharacter的字元(例如:+,@,#)\D:不是數字的字元\S:非空白字元\B:另外一側必須不是\w的字元OROperator針對[](bracket)也有其否定語法存在,作法就是在左邊括弧的右側加上一個^即可。

舉個例子來說:[^atiw]:非a,t,i,w的字元均符合[^x-z]:非x,y,z的字元均符合[^a-d0–5]:非a~d且非0~5的字元均符合GroupingandCapturing我們不是單純要知道輸入的字串是否符合正規表達式,還要抓出符合的部分。

舉個例子來說,我們透過09\d{8}簡易地抓出台灣的手機號碼。

但如果今天我所輸入的字串是myphonenumberis0912345678,這時候就需要加上()讓程式能夠幫我把括弧框起來的子字串存起來,如此一來就不用擔心使用者輸入不必要的文字。

以下介紹Grouping的用法:基本用法Enablegrouping:(yourpattern)ex:(09\d{8})Disablegrouping:(?:yourpattern)ex:(?:https?|ftp)Namedgrouping:(?yourpattern)ex:(?bar)前面有說到當你使用|來做oroperation會需要注意語意的問題,所以時常會借住group來減少語意錯誤的發生,但使用group也衍生額外的問題—產生不必要的group。

因此grouping才會有跳過群組的功能,就是為了避免冗員並讓我們能寫出較為簡潔的程式碼。

順帶一提,group是採用DFS做capturing。

比如說((abc)(def))(ghi)會變成abcdef、abc、def、ghi。

進階用法Backreference當我們在分析一個HTML檔案,必定會做tagmatching。

而為避免有人寫了不合法的tag,像是

……,我們需要在表達式中就可以直接取用前面group抓取到的結果。

也就是如此,衍生出backreference這樣的語法。

-order-based:\1、\2、\3…1..*Tryit!2.([a-zA-Z])([0-9])\2\1Tryit!-name-based:\k1.(?bar)\kTryit!PositiveLook-ahead/Look-behind在正規表達式中還定義了兩個有趣的語法,分別是look-ahead(?=)跟look-behind(?<=),而他們有一個共通點是「group是條件,不屬於比對結果」。

我們直接來看幾個範例:1.\d+(?=[a-z]{2})→給123ab456cd789則會挑出123和456,但不包含後面的英文字2.(?<=\$)\d+e→給1iphonecosts$699則會將699挑出而不包含$簡單來說,look-ahead跟look-behind的group雖然會被拿來做比對,但不會列入比對結果中,更不會被capture。

好處是我們可以做額外的filter,找出特定位置的目標字串。

NegativeLook-ahead/Look-behind特性一樣,差別只是其描述的是否定語句。

-Negativelook-ahead(?!)-Negativelook-behind(?



請為這篇文章評分?