久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      55分鐘學(xué)會(huì)正則表達(dá)式

      什么是正則

      正則表達(dá)式是一種用來(lái)描述一定數(shù)量文本的模式,用來(lái)匹配相同規(guī)范樣式的文本。在JavaScript中用RegExp對(duì)象表示正則表達(dá)式( 即Regular Eexpression),它是對(duì)字符串執(zhí)行模式匹配的強(qiáng)大工具。

      55分鐘學(xué)會(huì)正則表達(dá)式

      正則表達(dá)式是一種查找以及字符串替換操作。正則表達(dá)式在文本編輯器中廣泛使用,比如正則表達(dá)式被用于:

      • 檢查文本中是否含有指定的特征詞
      • 找出文中匹配特征詞的位置
      • 從文本中提取信息,比如:字符串的子串
      • 修改文本

      與文本編輯器相似,幾乎所有的高級(jí)編程語(yǔ)言都支持正則表達(dá)式。在這樣的語(yǔ)境下,“文本”也就是一個(gè)字符串,可以執(zhí)行的操作都是類似的。一些編程語(yǔ)言(比如Perl,JavaScript)會(huì)檢查正則表達(dá)式的語(yǔ)法。

      正則表達(dá)式是什么?

      正則表達(dá)式只是一個(gè)字符串。沒(méi)有長(zhǎng)度限制,但是,這樣的正則表達(dá)式長(zhǎng)度往往較短。如下所示是一些正則表達(dá)式的例子:

      • I had a S+ day today
      • [A-Za-z0-9-_]{3,16}
      • dddd-dd-dd
      • v(d+)(.d+)*
      • TotalMessages="(.*?)"
      • <[^<>]>

      這些字符串實(shí)際上都是微型計(jì)算機(jī)程序。正則表達(dá)式的語(yǔ)法,實(shí)際上是一種輕量級(jí)、簡(jiǎn)潔、適用于特定領(lǐng)域的編程語(yǔ)言。記住這一點(diǎn),那么你就很容易理解下面的事情:

      • 每一個(gè)正則表達(dá)式,都可以分解為一個(gè)指令序列,比如“先找到這樣的字符,再找到那樣的字符,再?gòu)闹姓业揭粋€(gè)字符。。?!?
      • 每一個(gè)正則表達(dá)式都有輸入(文本)和輸出(匹配規(guī)則的輸出,有時(shí)是修改后的文本)
      • 正則表達(dá)式有可能出現(xiàn)語(yǔ)法錯(cuò)誤――不是所有的字符串都是正則表達(dá)式
      • 正則表達(dá)式語(yǔ)法很有個(gè)性,也可以說(shuō)很恐怖
      • 有時(shí)可以通過(guò)編譯,使得正則表達(dá)式執(zhí)行更快

      在實(shí)現(xiàn)中,正則表達(dá)式還有其他的特點(diǎn)。本文將重點(diǎn)討論正則表達(dá)式的核心語(yǔ)法,在幾乎所有的正則表達(dá)式中都可以見(jiàn)到這些規(guī)則。

      特別提示:正則表達(dá)式與文件通配語(yǔ)法無(wú)關(guān),比如 *.xml

      正則表達(dá)式的基礎(chǔ)語(yǔ)法

      字符

      正則表達(dá)式中包含了一系列的字符,這些字符只能匹配它們本身。有一些被稱為“元字符”的特殊字符,可以匹配一些特殊規(guī)則。

      如下所示的例子中,我用紅色標(biāo)出了元字符。

      • I had a S+ day today
      • [A-Za-z0-9-_]{3,16}
      • dddd-dd-dd
      • v(d+)(.d+)*
      • TotalMessages="(.*?)"
      • <[^<>]*>

      大部分的字符,包括所有的字母和數(shù)字字符,是普通字符。也就意味著,它們只能匹配它們自己,如下所示的正則表達(dá)式:

      cat

      意味著,只能匹配一個(gè)字符串,以“c”開頭,然后是字符“a”,緊跟著是字符“t”的字符串。

      到目前為止,正則表達(dá)式的功能類似于

      • 常規(guī)的Find功能
      • Java中的 String.indexOf() 函數(shù)
      • PHP中的 strpos()函數(shù)
      • 等等

      注意:不做特殊說(shuō)明,正則表達(dá)式中是區(qū)分大小寫的。但是,幾乎所有正則表達(dá)式的實(shí)現(xiàn),都會(huì)提供一個(gè)Flag用來(lái)控制是否區(qū)分大小寫。

      點(diǎn)“.”

      我們第一個(gè)要講解的元字符是“.”。這個(gè)符號(hào)意味著可以匹配任意一個(gè)字符。如下所示的正則表達(dá)式:

      c.t

      意味著匹配“以c開頭,之后是任意一個(gè)字符,緊跟著是字母t”的字符串。

      在一段文本中,這樣的正則表達(dá)式可以用來(lái)找出cat, cot, czt這樣的字符串,甚至可以找出c.t這樣的組合,但是不能找到ct或者是coot這樣的字符串。

      使用反斜杠“”可以忽略元字符,使得元字符的功能與普通字符一樣。所以,正則表達(dá)式

      c.t

      表示“找到字母c,然后是一個(gè)句號(hào)(“.”),緊跟著字母t”

      反斜杠本身也是一個(gè)元字符,這意味著反斜杠本身也可以通過(guò)相似的方法變回到普通字符的用途。因此,正則表達(dá)式

      c\t

      表示匹配“以字符c開頭,然后是一個(gè)反斜杠,緊跟著是字母t”的字符串。

      注意!在正則表達(dá)式的實(shí)現(xiàn)中,.是不能用于匹配換行符的?!睋Q行符“的表示方法在不同實(shí)現(xiàn)中也不同。實(shí)際編程時(shí),請(qǐng)參考相關(guān)文檔。在本文中,我認(rèn)為.是可以匹配任意字符的。實(shí)現(xiàn)環(huán)境通常會(huì)提供一個(gè)Flag標(biāo)志位,來(lái)控制這一點(diǎn)。

      字符類

      字符類是一組在方括號(hào)內(nèi)的字符,表示可以匹配其中的任何一個(gè)字符。

      • 正則表達(dá)式c[aeiou]t,表示可以匹配的字符串是”以c開頭,接著是aeiou中的任何一個(gè)字符,最后以t結(jié)尾”。在文本的實(shí)際應(yīng)用中,這樣的正則表達(dá)式可以匹配:cat,cet,cit,cot,cut五種字符串。
      • 正則表達(dá)式[0123456789]表示匹配任意一個(gè)整數(shù)。
      • 正則表達(dá)式[a]表示匹配單字符a。

      包含忽略字符的例子

      • [a]

        表示匹配字符串[a]

      • [[]ab]表示匹配的字符為”[“或者”]”或者”a”,或者”b”
      • [\[]]表示匹配的字符為””或者 “[”或者”]”

      在字符類中,字符的重復(fù)和出現(xiàn)順序并不重要。[dabaaabcc]與[abc]是相同的

      重要提示:字符類中和字符類外的規(guī)則有時(shí)不同,一些字符在字符類中是元字符,在字符類外是普通字符。一些字符正好相反。還有一些字符在字符類中和字符類外都是元字符,這要視情況而定!

      比如,.表示匹配任意一個(gè)字符,而[.]表示匹配一個(gè)全角句號(hào)。這不是一回事!

      字符類的范圍

      在字符集中,你可以通過(guò)使用短橫線來(lái)表示匹配字母或數(shù)字的范圍。

      • [b-f]與[b,c,d,e,f]相同,都是匹配一個(gè)字符”b”或”c”或”d”或”e”或”f”
      • [A-Z]與[ABCDEFGHIJKLMNOPQRSTUVWXYZ]相同,都是匹配任意一個(gè)大寫字母。
      • [1-9]與[123456789]相同,都是匹配任意一個(gè)非零數(shù)字。

      練習(xí)

      使用目前我們已經(jīng)講解的正則表達(dá)式相關(guān)知識(shí),在字典中匹配找到含有最多連續(xù)元音的單詞,同時(shí)找到含有最多連續(xù)輔音的單詞。

      答案

      [aeiou][aeiou][aeiou][aeiou][aeiou][aeiou] 這樣的正則表達(dá)式,可以匹配連續(xù)含有六個(gè)元音的單詞,比如 euouae 和 euouaes。

      同樣的,恐怖的正則表達(dá)式[bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz] 可以找到連續(xù)含有十個(gè)輔音的單詞sulphhydryls.

      下文中,我們會(huì)講解,怎樣有效縮短這樣的正則表達(dá)式長(zhǎng)度。

      在字符類之外,短橫線沒(méi)有特殊含義。正則表達(dá)式a-z,表示匹配字符串“以a開頭,然后是一個(gè)短橫線,以z結(jié)尾”。

      范圍和單獨(dú)的字符可能在一個(gè)字符類中同時(shí)出現(xiàn):

      • [0-9.,]表明匹配一個(gè)數(shù)字,或者一個(gè)全角句號(hào),或者一個(gè)逗號(hào)
      • [0-9a-fA-F]意味著匹配一個(gè)十六進(jìn)制數(shù)
      • [a-zA-Z0-9-]意味著匹配一個(gè)字母、數(shù)字或者一個(gè)短橫線

      練習(xí)

      使用已經(jīng)介紹過(guò)的正則表達(dá)式知識(shí),匹配YYYY-MM-DD格式的日期。

      答案

      [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].

      同樣的,下文中,我們會(huì)介紹怎樣有效減少這樣的正則表達(dá)式長(zhǎng)度。

      雖然你可以嘗試在正則表達(dá)式中使用一些非字母或數(shù)字作為范圍的最后一個(gè)符號(hào),比如abc[!-/]def,但是這并不是在每種實(shí)現(xiàn)中都合法。即使這樣的語(yǔ)法是合法的,這樣的語(yǔ)義也是模糊的。最好不要這樣使用。

      同時(shí),你必須謹(jǐn)慎選擇范圍的邊界值。即使[A-z]在你使用的實(shí)現(xiàn)中,是合法的,也可能會(huì)產(chǎn)生無(wú)法預(yù)料的運(yùn)行結(jié)果。(注意,在z到a之間,是有字符存在的)

      注意:范圍的字符值代表的是字符而已,并不能代表數(shù)值范圍,比如[1-31]表示匹配一個(gè)數(shù)字,是1或者2或者3,而不是匹配一個(gè)數(shù)值在1到31之間的數(shù)。

      字符類的反義

      你可以在字符類的起始位放一個(gè)反義符。

      • [^a]表示匹配任何不是“a”的字符
      • [^a-zA-Z0-9]表示匹配任何不是字母也不是數(shù)字的字符
      • [^abc]匹配一個(gè)為“^”或者a或者b或者c的字符
      • [^^]表示匹配任何不為“^”的字符

      練習(xí)

      在字典中,找到一個(gè)不滿足“在e之前有i,但是沒(méi)有c”的例子。

      答案

      cie和[^c]ei都要可以找到很多這樣的例子,比如ancient,science,viel,weigh

      轉(zhuǎn)義字符類

      d這個(gè)正則表達(dá)式與[0-9]作用相同,都是匹配任何一個(gè)數(shù)字。(要匹配d,應(yīng)該使用正則表達(dá)式\d)

      w與[0-9A-Za-z]相同,都表示匹配一個(gè)數(shù)字或字母字符

      s意味著匹配一個(gè)空字符(空格,制表符,回車或者換行)

      另外

      • D與[^0-9]相同,表示匹配一個(gè)非數(shù)字字符。
      • W與[^0-9A-Za-z]相同,表示匹配一個(gè)非數(shù)字同時(shí)不是字母的字符。
      • S表示匹配一個(gè)非空字符。

      這些是你必須掌握的字符。你可能已經(jīng)注意到了,一個(gè)全角句號(hào)“.”也是一個(gè)字符類,可以匹配任意一個(gè)字符。

      很多正則表達(dá)式的實(shí)現(xiàn)中,提供了更多的字符類,或者是標(biāo)志位在ASCII碼的基礎(chǔ)上,擴(kuò)展現(xiàn)有的字符類。

      特別提示:統(tǒng)一字符集中包含除了0至9之外的更多數(shù)字字符,同樣的,也包含更多的空字符和字母字符。實(shí)際使用正則表達(dá)式時(shí),請(qǐng)仔細(xì)查看相關(guān)文檔。

      練習(xí)

      簡(jiǎn)化正則表達(dá)式 [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].

      答案

      dddd-dd-dd.

      重復(fù)

      在字符或字符集之后,你可以使用{ }大括號(hào)來(lái)表示重復(fù)

      • 正則表達(dá)式a{1}與a意思相同,都表示匹配字母a
      • a{3}表示匹配字符串“aaa”
      • a{0}表示匹配空字符串。從這個(gè)正則表達(dá)式本身來(lái)看,它毫無(wú)意義。如果你對(duì)任何文本執(zhí)行這樣的正則表達(dá)式,你可以定位到搜索的起始位置,即使文本為空。
      • a{2}表示匹配字符串“a{2}”
      • 在字符類中,大括號(hào)沒(méi)有特殊含義。[{}]表示匹配一個(gè)左邊的大括號(hào),或者一個(gè)右邊的大括號(hào)

      練習(xí)

      簡(jiǎn)化下面的正則表達(dá)式

      • z.......z
      • dddd-dd-dd
      • [aeiou][aeiou][aeiou][aeiou][aeiou][aeiou]
      • [bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz]

      答案

      • z.{7}z
      • d{4}-d{2}-d{2}
      • [aeiou]{6}
      • [bcdfghjklmnpqrstvwxyz]{10}

      注意:重復(fù)字符是沒(méi)有記憶性的,比如[abc]{2}表示先匹配”a或者b或者c”,再匹配”a或者b或者c”,與匹配”aa或者ab或者ac或者ba或者bb或者bc或者ca或者cb或者cc“一樣。[abc]{2}并不能表示匹配”aa或者bb或者cc“

      指定重復(fù)次數(shù)范圍

      重復(fù)次數(shù)是可以指定范圍的

      • x{4,4}與x{4}相同
      • colou{0,1}r表示匹配colour或者color
      • a{3,5}表示匹配aaaaa或者aaaa或者aaa

      注意這樣的正則表達(dá)式會(huì)優(yōu)先匹配最長(zhǎng)字符串,比如輸入 I had an aaaaawful day會(huì)匹配單詞aaaaawful中的aaaaa,而不會(huì)匹配其中的aaa。

      重復(fù)次數(shù)是可以有范圍的,但是有時(shí)候這樣的方法也不能找到最佳答案。如果你的輸入文本是I had an aaawful daaaaay那么在第一次匹配時(shí),只能找到aaawful,只有再次執(zhí)行匹配時(shí)才能找到daaaaay中的aaaaa.

      重復(fù)次數(shù)的范圍可以是開區(qū)間

      • a{1,}表示匹配一個(gè)或一個(gè)以上的連續(xù)字符a。依然是匹配最長(zhǎng)字符串。當(dāng)找到第一個(gè)a之后,正則表達(dá)式會(huì)嘗試匹配盡量多個(gè)的連續(xù)字母a。
      • .{0,}表示匹配任意內(nèi)容。無(wú)論你輸入的文本是什么,即使是一個(gè)空字符串,這個(gè)正則表達(dá)式都會(huì)成功匹配全文并返回結(jié)果。

      練習(xí)

      使用正則表達(dá)式找到雙引號(hào)。要求輸入字符串可能包含任意個(gè)字符。

      調(diào)整你的正則表達(dá)式使得在一對(duì)雙引號(hào)中間不再包含其他的雙引號(hào)。

      答案

      “.{0,}”, 然后 “[^”]{0,}”.

      關(guān)于重復(fù)的轉(zhuǎn)義字符

      ?與{0,1}相同,比如,colou?r表示匹配colour或者color

      *與{0,}相同。比如,.*表示匹配任意內(nèi)容

      +與{1,}相同。比如,w+表示匹配一個(gè)詞。其中”一個(gè)詞”表示由一個(gè)或一個(gè)以上的字符組成的字符串,比如_var或者AccountName1.

      這些是你必須知道的常用轉(zhuǎn)義字符,除此之外還有:

      • ?*+ 表示匹配字符串”?*+”
      • [?*+]表示匹配一個(gè)問(wèn)號(hào),或者一個(gè)*號(hào),或者一個(gè)加號(hào)

      練習(xí)

      簡(jiǎn)化下列的正則表達(dá)式:

      • ".{0,}" and "[^"]{0,}"
      • x?x?x?
      • y*y*
      • z+z+z+z+

      答案

      • ".*" and "[^"]*"
      • x{0,3}
      • y*
      • z{4,}

      練習(xí)

      寫出正則表達(dá)式,尋找由非字母字符分隔的兩個(gè)單詞。如果是三個(gè)呢?六個(gè)呢?

      w+W+w+, w+W+w+W+w+, w+W+w+W+w+W+w+W+w+W+w+.

      下文中,我們將簡(jiǎn)化這個(gè)正則表達(dá)式。

      非貪婪匹配

      正則表達(dá)式 “.*” 表示匹配雙引號(hào),之后是任意內(nèi)容,之后再匹配一個(gè)雙引號(hào)。注意,其中匹配任意內(nèi)容也可以是雙引號(hào)。通常情況下,這并不是很有用。通過(guò)在句尾加上一個(gè)問(wèn)號(hào),可以使得字符串重復(fù)不再匹配最長(zhǎng)字符。

      • d{4,5}?表示匹配dddd或者ddddd。也就是和d{4}一樣
      • colou??r與colou{0,1}r相同,表示找到color或者colour。這與colou?r一樣。
      • “.*?”表示先匹配一個(gè)雙引號(hào),然后匹配最少的字符,然后是一個(gè)雙引號(hào),與上面兩個(gè)例子不同,這很有用。

      選擇匹配

      你可以使用|來(lái)分隔可以匹配的不同選擇:

      • cat|dog表示匹配”cat”或者”dog”
      • red|blue|以及red||blue以及|red|blue都表示匹配red或者blue或者一個(gè)空字符串
      • a|b|c與[abc]相同
      • cat|dog||表示匹配”cat”或者”dog”或者一個(gè)分隔符”|“
      • [cat|dog]表示匹配a或者c或者d或者g或者o或者t或者一個(gè)分隔符“|”

      練習(xí)

      簡(jiǎn)化下列正則表達(dá)式:

      • s|t|u|v|w
      • aa|ab|ba|bb
      • [abc]|[^abc]
      • [^ab]|[^bc]
      • [ab][ab][ab]?[ab]?

      答案

      • [s-w]
      • [ab]{2}
      • .
      • [^b]
      • [ab]{2,4}

      練習(xí)

      使用正則表達(dá)式匹配1到31之間的整數(shù),[1-31]不是正確答案!

      這樣的正則表達(dá)式不唯一. [1-9]|[12][0-9]|3[01] 是其中之一。

      分組

      你可以使用括號(hào)表示分組:

      • 通過(guò)使用 Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day 匹配一周中的某一天
      • (w*)ility w*ility 相同。都是匹配一個(gè)由”ility”結(jié)尾的單詞。稍后我們會(huì)講解,為何第一種方法更加有用。
      • ()表示匹配一對(duì)括號(hào)。
      • [()]表示匹配任意一個(gè)左括號(hào)或者一個(gè)右括號(hào)

      練習(xí)

      在《時(shí)間機(jī)器中》找到一對(duì)括號(hào)中的內(nèi)容,然后通過(guò)修改正則表達(dá)式,找到不含括號(hào)的內(nèi)容。

      答案

      [Math Processing Error]. 然后是, [Math Processing Error].

      分組可以包括空字符串:

      • (red|blue)表示匹配red或者blue或者是一個(gè)空字符串
      • abc()def與abcdef相同

      你也可以在分組的基礎(chǔ)上使用重復(fù):

      • (red|blue)?與(red|blue|)相同
      • w+(s+w+)表示匹配一個(gè)或多個(gè)由空格分隔的單詞

      練習(xí)

      簡(jiǎn)化正則表達(dá)式 w+W+w+W+w+ 以及 w+W+w+W+w+W+w+W+w+W+w+.

      答案

      w+(W+w+){2}, w+(W+w+){5}.

      單詞分隔符

      在單詞和非單詞之間有單詞分隔符。記住,一個(gè)單詞w是[0-9A-Za-z_],而非單詞字符是W(大寫),表示[^0-9A-Za-z_].

      在文本的開頭和結(jié)尾通常也有單詞分隔符。

      在輸入文本it’s a cat中,實(shí)際有八個(gè)單詞分隔符。如果我們?cè)赾at之后在上一個(gè)空格,那就有九個(gè)單詞分隔符。.

      • b表示匹配一個(gè)單詞分隔符
      • bwwwb表示匹配一個(gè)三字母單詞
      • aba表示匹配兩個(gè)a中間有一個(gè)單詞分隔符。這個(gè)正則表達(dá)式永遠(yuǎn)不會(huì)有匹配的字符,無(wú)論輸入怎樣的文本。

      單詞分隔符本身并不是字符。它們的寬度為0。下列正則表達(dá)式的作用不同

      • (bcat)b
      • (bcatb)
      • b(cat)b
      • b(catb)

      練習(xí)

      在詞典中找到最長(zhǎng)的單詞。

      答案

      在嘗試之后發(fā)現(xiàn),b.{45,}b可以在字典中找到最長(zhǎng)單詞

      換行符

      一篇文本中可以有一行或多行,行與行之間由換行符分隔,比如:

      • Line一行文字
      • Line break換行符
      • Line一行文字
      • Line break換行符
      • Line break換行符
      • Line一行文字

      注意,所有的文本都是以一行結(jié)束的,而不是以換行符結(jié)束。但是,任意一行都可能為空,包括最后一行。

      行的起始位置,是在換行符和下一行首字符之間的空間。考慮到單詞分隔符,文本的起始位置也可以當(dāng)做是首行位置。

      最后一行是最后一行的尾字符和換行符之間的空間??紤]到單詞分隔符,文本的結(jié)束也可以認(rèn)為是行的結(jié)束。

      那么新的格式表示如下:

      • Start-of-line, line, end-of-line
      • Line break
      • Start-of-line, line, end-of-line
      • Line break
      • Line break
      • Start-of-line, line, end-of-line

      基于上述概念:

      • ^表示匹配行的開始位置
      • $表示匹配行的結(jié)束位置
      • ^&表示一個(gè)空行
      • ^.*& 表示匹配全文內(nèi)容,因?yàn)樾械拈_始符號(hào)也是一個(gè)字符,"."會(huì)匹配這個(gè)符號(hào)。找到單獨(dú)的一行,可以使用 ^.*?$
      • ^$表示匹配字符串“^$”
      • [$]表示匹配一個(gè)$。但是,[^]不是合法的正則表達(dá)式。記住在方括號(hào)中,字符有不同的特殊含義。要想在方括號(hào)內(nèi)匹配^,必須用[^]

      與字符分隔符一樣,換行符也不是字符。它們寬度為0.如下所示的正則表達(dá)式作用不同:

      • (^cat)$
      • (^cat$)
      • ^(cat)$
      • ^(cat$)

      練習(xí)

      使用正則表達(dá)式在《時(shí)間機(jī)器》中找到最長(zhǎng)的一行。

      答案

      使用正則表達(dá)式^.{73,}$可以匹配長(zhǎng)度為73的一行

      文本分界

      在很多的正則表達(dá)式實(shí)現(xiàn)中,將^和$作為文本的開始符號(hào)和結(jié)束符號(hào)。

      還有一些實(shí)現(xiàn)中,用A和z作為文本的開始和結(jié)束符號(hào)。

      捕捉和替換

      從這里開始,正則表達(dá)式真正體現(xiàn)出了它的強(qiáng)大。

      捕獲組

      你已經(jīng)知道了使用括號(hào)可以匹配一組符號(hào)。使用括號(hào)也可以捕獲子串。假設(shè)正則表達(dá)式是一個(gè)小型計(jì)算機(jī)程序,那么捕獲子串就是它輸出的一部分。

      正則表達(dá)式(w*)ility表示匹配以ility結(jié)尾的詞。第一個(gè)被捕獲的部分是由w*控制的。比如,輸入的文本內(nèi)容中有單詞accessibility,那么首先被捕獲的部分是accessib。如果輸入的文本中有單獨(dú)的ility,則首先被捕獲的是一個(gè)空字符串。

      你可能會(huì)有很多的捕獲字符串,它們可能靠得很近。捕獲組從左向右編號(hào)。也就是只需要對(duì)左括號(hào)計(jì)數(shù)。

      假設(shè)有這樣的正則表達(dá)式:(w+) had a ((w+) w+)

      輸入的內(nèi)容是:I had a nice day

      • 捕獲組1:I
      • 捕獲組2:nice day
      • 捕獲組3:nice

      在一些正則表達(dá)式的實(shí)現(xiàn)中,你可以從零開始編號(hào),編號(hào)零表示匹配整句話:I had a nice day.

      在其他的實(shí)現(xiàn)中,如果沒(méi)有制定捕獲組,那么捕獲組1會(huì)自動(dòng)地填入捕獲組0的信息。

      是的,這也意味著會(huì)有很多的括號(hào)。有一些正則表達(dá)式的實(shí)現(xiàn)中,提供了“非捕獲組”的語(yǔ)法,但是這樣的語(yǔ)法并不是標(biāo)準(zhǔn)語(yǔ)法,因此我們不會(huì)介紹。

      從一個(gè)成功的匹配中返回的捕獲組個(gè)數(shù),與使用原來(lái)的正則表達(dá)式獲得的捕獲組個(gè)數(shù)相同。記住這一點(diǎn),你可以解釋一些奇怪的現(xiàn)象。.

      正則表達(dá)式((cat)|dog)表示匹配cat或者dog。這里有兩個(gè)捕獲組,如果輸入文本是dog,那么捕獲組1是dog,捕獲組2為空。

      正則表達(dá)式a(w)*表示匹配一個(gè)以a開頭的單詞。這里只有一個(gè)捕獲組

      • 如果輸入文本為a,捕獲組1為空。
      • 如果輸入文本為ad,捕獲組為d
      • 如果輸入文本為avocado,捕獲組1為v。但是捕獲組0表示整個(gè)單詞avocado.

      替換

      假如你使用了一個(gè)正則表達(dá)式去匹配字符串,你可以描述另外一個(gè)字符串來(lái)替換其中的匹配字符。用來(lái)替換的字符串稱為替換表達(dá)式。它的功能類似于

      • 常規(guī)的Replace會(huì)話
      • Java中的String.replace()函數(shù)
      • PHP的str_replace()函數(shù)
      • 等等

      練習(xí)

      將《時(shí)間機(jī)器》中所有的元音字母替換為r。

      答案

      使用正則表達(dá)式[aeiou]以及[AEIOU],對(duì)應(yīng)的替換字符串分別為r,R.

      但是,你可以在替換表達(dá)式中引用捕獲組。這是在替換表達(dá)式中,你可以唯一操作的地方。這也是非常有效的,因?yàn)檫@樣你就不用重構(gòu)你找到的字符串。

      假設(shè)你正在嘗試將美國(guó)風(fēng)格的日期表示MM/DD/YY替換為ISO 8601日期表示YYYY-MM-DD

      • 從正則表達(dá)式(dd)/(dd)/(dd)開始。注意,這其中有三個(gè)捕獲組:月份,日期和兩位的年份。
      • .捕獲組的內(nèi)容和捕獲組編號(hào)之間用反斜杠分隔,因此你的替換表達(dá)式應(yīng)該是203-1-2.
      • 如果我們輸入的文本中包含03/04/05表示2005年3月4日那么:
        • 捕獲組1:03
        • 捕獲組2:04
        • 捕獲組3:05
        • 替換字符串2005-03-04.

      在替換表達(dá)式中,你可以多次使用捕獲組

      • 對(duì)于雙元音,正則表達(dá)式為([aeiou]),替換表達(dá)式為ll
      • 在替換表達(dá)式中不能使用反斜杠。比如,你在計(jì)算機(jī)程序中希望使用字符串中使用部分文本。那么,你必須在每個(gè)雙引號(hào)或者反斜杠之前加上反斜杠。
      • 你的正則表達(dá)式可以是([\”])。捕獲組1是雙引號(hào)或者反斜杠
      • 你的替換表達(dá)式應(yīng)該是\l

      在某些實(shí)現(xiàn)中,采用美元符號(hào)$代替

      練習(xí)

      使用正則表達(dá)式和替換表達(dá)式,將23h59這樣的時(shí)間戳轉(zhuǎn)化為23:59.

      答案

      正則表達(dá)式finds the timestamps, 替換表達(dá)式1:2

      反向引用

      在一個(gè)正則表達(dá)式中,你也可以引用捕獲組。這稱作:反向引用

      比如,[abc]{2}表示匹配aa或者ab或者ac或者ba或者bb或者bc或者ca或者cb或者cc.但是{[abc]}1表示只匹配aa或者bb或者cc.

      練習(xí)

      在字典中,找到包含兩次重復(fù)子串的最長(zhǎng)單詞,比如papa, coco

      b(.{6,})1b 匹配 chiquichiqui.

      如果我們不在乎單詞的完整性,我們可以忽略單詞的分解,使用正則表達(dá)式 (.{7,})1匹配countercountermeasure 以及 countercountermeasures.

      使用正則表達(dá)式編程

      特別提醒:

      過(guò)度使用的反斜杠

      在一些編程語(yǔ)言,比如Java中,對(duì)于包含正則表達(dá)式的字符串沒(méi)有特殊標(biāo)記。字符串有著自己的過(guò)濾規(guī)則,這是優(yōu)先于正則表達(dá)式規(guī)則的,這是頻繁使用反斜杠的原因。

      比如在Java中

      • 匹配一個(gè)數(shù)字,使用的正則表達(dá)式從d變?yōu)榇a中的String re= “\d”
      • 匹配雙引號(hào)字符串的正則表達(dá)式從"[^"]*" 變?yōu)镾tring re = “”[^”]*””
      • 匹配反斜杠或者是左邊方括號(hào),或者右邊方括號(hào)的正則表達(dá)式從[\[]] 變?yōu)?/span>String re = “[\\

        [\]

        ]”;

      • String re = "\s";String re = "[ trn]"; 是等價(jià)的. 注意它們實(shí)際執(zhí)行調(diào)用時(shí)的層次不同。

      在其他的編程語(yǔ)言中,正則表達(dá)式是由特殊標(biāo)明的,比如使用/。下面是JavaScript的例子:

      • 匹配一個(gè)數(shù)字,d會(huì)簡(jiǎn)單寫成 var regExp = /d/;.
      • 匹配一個(gè)反斜杠或者一個(gè)左邊的方括號(hào)或者一個(gè)右邊的方括號(hào), var regExp = /[\[]]/;
      • var regExp = /s/;var regExp = /[ trn]/; 是等價(jià)的
      • 當(dāng)然,這意味著在使用/時(shí)必須重復(fù)兩次。比如找到URL必須使用var regExp = /https?:///;.

      我希望現(xiàn)在你能明白,我為什么讓你特別注意反斜杠。

      動(dòng)態(tài)正則表達(dá)式

      當(dāng)你動(dòng)態(tài)創(chuàng)建一個(gè)正則表達(dá)式的時(shí)候請(qǐng)?zhí)貏e小心。如果你使用的字符串不夠完善的花,可能會(huì)有意想不到的匹配結(jié)果。這可能導(dǎo)致語(yǔ)法錯(cuò)誤,更糟糕的是,你的正則表達(dá)式語(yǔ)法正確,但是結(jié)果無(wú)法預(yù)料。

      錯(cuò)誤的Java代碼:

      String sep = System.getProperty(“file.separator”); String[] directories = filePath.split(sep);

      Bug:String.split() 認(rèn)為sep是一個(gè)正則表達(dá)式。但是,在Windows中,Sep是表示匹配一個(gè)反斜杠,也就是與正則表達(dá)式”\”相同。這個(gè)正則表達(dá)式是正確的,但是會(huì)返回一個(gè)異常:PatternSyntaxException.

      任何好的編程語(yǔ)言都會(huì)提供一種良好的機(jī)制來(lái)跳過(guò)字符串中所有的元字符。在Java中,你可以這樣實(shí)現(xiàn):

      String sep = System.getProperty(“file.separator”);

      String[] directories = filePath.split(Pattern.quote(sep));

      循環(huán)中的正則表達(dá)式

      將正則表達(dá)式字符串加入反復(fù)運(yùn)行的程序中,是一種開銷很大的操作。如果你可以在循環(huán)中避免使用正則表達(dá)式,你可以大大提高效率。

      其他建議

      輸入驗(yàn)證

      正則表達(dá)式可以用來(lái)進(jìn)行輸入驗(yàn)證。但是嚴(yán)格的輸入驗(yàn)證會(huì)使得用戶體驗(yàn)較差。比如:信用卡號(hào)

      在一個(gè)網(wǎng)站上,我輸入了我的卡號(hào)比如 1234 5678 8765 4321 網(wǎng)站拒絕接收。因?yàn)樗褂昧苏齽t表達(dá)式d{16}。

      正則表達(dá)式應(yīng)該考慮到用戶輸入的空格和短橫線。

      實(shí)際上,為什么不先過(guò)濾掉所有的非數(shù)字字符,然后再進(jìn)行有效性驗(yàn)證呢?這樣做,可以先使用D以及空的替換表達(dá)式。

      練習(xí)

      在不先過(guò)濾掉所有的非數(shù)字字符的情況下,使用正則表達(dá)式驗(yàn)證卡號(hào)的正確性。

      答案

      D*(dD*){16} is one of several variations which would accomplish this.

      名字

      不要使用正則表達(dá)式來(lái)驗(yàn)證姓名。實(shí)際上,即使可以,也不要企圖驗(yàn)證姓名。

      程序員對(duì)名字的錯(cuò)誤看法:

      • 名字中不含空格
      • 名字中沒(méi)有連接符號(hào)
      • 名字中只會(huì)使用ASCII碼字符
      • 名字中出現(xiàn)的字都在特殊字符集中
      • 名字至少要有M個(gè)字的長(zhǎng)度
      • 名字不會(huì)超過(guò)N個(gè)字的長(zhǎng)度
      • 人們只有一個(gè)名
      • 人們只有一個(gè)中間名
      • 人們只有一個(gè)姓(最后三條是從英語(yǔ)的人名考慮)

      電子郵件地址

      不要使用正則表達(dá)式驗(yàn)證郵箱地址的正確性。

      首先,這樣的驗(yàn)證很難是精確的。電子郵件地址是可以用正則表達(dá)式驗(yàn)證的,但是表達(dá)式會(huì)非常的長(zhǎng)并且復(fù)雜。

      短的正則表達(dá)式會(huì)導(dǎo)致錯(cuò)誤。(你知道嗎?電子郵箱地址中會(huì)有一些注釋)

      第二,即使一個(gè)電子郵件地址可以成功匹配正則表達(dá)式,也不代表這個(gè)郵箱實(shí)際存在。郵箱的唯一驗(yàn)證方法,是發(fā)送驗(yàn)證郵件。

      注意

      在嚴(yán)格的應(yīng)用場(chǎng)景中,不要使用正則表達(dá)式來(lái)解析HTML或者XML。解析HTML或者XML:

      使用簡(jiǎn)單的正則表達(dá)式不能完成總體來(lái)說(shuō)非常困難已經(jīng)有其他的方法解決找到一個(gè)已經(jīng)有的解析庫(kù)來(lái)完成這個(gè)工作

      這就是55分鐘的全部?jī)?nèi)容

      總結(jié):

      • 字符: a b c d 1 2 3 4 etc.
      • 字符類: . [abc] [a-z] d w s
        • . 代表任何字符
        • d 表示“數(shù)字”
        • w 表示”字母”, [0-9A-Za-z_]
        • s 表示 “空格, 制表符,回車或換行符”
        • 否定字符類: [^abc] D W S
      • 重復(fù): {4} {3,16} {1,} ? * +
        • ? 表示 “零次或一次”
        • * 表示 “大于零次”
        • + 表示 “一次或一次以上”
        • 如果不加上?,所有的重復(fù)都是最長(zhǎng)匹配的(貪婪)
      • 分組: (Septem|Octo|Novem|Decem)ber
      • 詞,行以及文本的分隔: b ^ $ A z
      • 轉(zhuǎn)義字符: 1 2 3 etc. (在匹配表達(dá)式和替換表達(dá)式中都可用)
      • 元字符: . [ ] { } ? * + | ( ) ^ $
      • 在字符類中使用元字符: [ ] - ^
      • 使用反斜杠可以忽略元字符:

      致謝

      正則表達(dá)式非常常用而且非常有用。每個(gè)人在編輯文本或是編寫程序時(shí)都必須了解怎樣使用正則表達(dá)式。

      如果感覺(jué)上面的不夠細(xì)致推薦大家查看這篇文章:

      正則表達(dá)式30分鐘入門教程

      正則表達(dá)式速查表

      Learn regular expressions in about 55 minutes 英文版本

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)