欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:mysql 9. 正則表達式

柚子快報激活碼778899分享:mysql 9. 正則表達式

http://yzkb.51969.com/

????????編程工具和技術是以一種混亂、進化的方式生存和傳播的。獲勝的并不總是最好或最杰出的工具,而是那些在合適的利基市場中發(fā)揮足夠好的功能,或者恰好與另一項成功的技術相結(jié)合的工具。

????????在本章中,我將討論這樣一種工具--正則表達式。正則表達式是一種描述字符串數(shù)據(jù)模式的方法。正則表達式是一種描述字符串數(shù)據(jù)中模式的方法,它是一種獨立的小語言,是 JavaScript 以及其他許多語言和系統(tǒng)的一部分。

????????正則表達式既非常笨拙,又非常有用。它們的語法令人費解,JavaScript 為它們提供的編程接口也很笨拙。但它們卻是檢查和處理字符串的強大工具。正確理解正則表達式將使你成為一名更高效的程序員。

創(chuàng)建正則表達式

????????正則表達式是一種對象類型。它既可以用 RegExp 構(gòu)造函數(shù)構(gòu)造,也可以用正斜杠 (/) 字符將模式括起來寫成文字值。

這兩個正則表達式對象表示相同的模式:一個 a 字符后接一個 b 字符后接一個 c 字符。

在使用 RegExp 構(gòu)造函數(shù)時,模式被寫成普通字符串,因此通常的規(guī)則適用于反斜線。

第二種符號,即模式出現(xiàn)在斜線字符之間,對反斜線的處理略有不同。首先,由于正斜線會結(jié)束模式,因此我們需要在希望成為模式一部分的正斜線前加上反斜線。此外,不屬于特殊字符代碼(如 \n)的反斜線將被保留,而不是像在字符串中那樣被忽略,從而改變模式的含義。某些字符(如?和+)在正則表達式中具有特殊含義,如果要表示字符本身,則必須在其前面加上反斜線。

測試匹配度

????????正則表達式對象有許多方法。最簡單的方法是測試。如果你向它傳遞一個字符串,它將返回一個布爾值,告訴你該字符串是否包含表達式中的匹配模式。

????????由非特殊字符組成的正則表達式只表示該字符序列。如果 abc 出現(xiàn)在我們要測試的字符串的任何位置(而不僅僅是開頭),test 將返回 true。

字符集

????????調(diào)用 indexOf 也可以查出一個字符串是否包含 abc。正則表達式非常有用,因為它允許我們描述更復雜的模式。

????????比方說,我們想匹配任何數(shù)字。在正則表達式中,將一組字符放在方括號中,表達式的這一部分就會匹配方括號中的任何字符。

下面兩個表達式都匹配所有包含數(shù)字的字符串:

????????在方括號內(nèi),兩個字符之間的連字符 (-) 可用來表示一系列字符,其排序由字符的 Unicode 編號決定。在這種排序中,字符 0 至 9 緊挨在一起(代碼 48 至 57),因此 [0-9] 涵蓋了所有字符,并可與任何數(shù)字匹配。

一些常見字符組有自己的內(nèi)置快捷鍵。數(shù)字就是其中之一: \d "與[0-9]的意思相同。

\d 只有包含數(shù)字字符,為true;否則為:false \w 只有包含字母數(shù)字字符("單詞字符),為true;否則為:false \s 只有包含空白字符(空格、制表符、換行符及類似字符),為:true;否則為:false \D 只有數(shù)字,為:false;否則為:true \W 只有字母和數(shù)字,為:false;否則為:true \S 只有非空格、制表符、換行符及類似字符,為:false,否則為:true . 只有換行符(\t),為false;否則為:true

你可以用下面的表達式來匹配日期和時間格式,如 01-30-2003 15:20:

????????這個正則表達式看起來非常糟糕,不是嗎?其中一半是反斜線,產(chǎn)生了背景噪音,很難發(fā)現(xiàn)實際表達的模式。稍后我們將看到這個表達式的一個稍加改進的版本。

????????這些反斜線代碼也可以用在方括號內(nèi)。例如,[\d.] 表示任何數(shù)字或句點字符。方括號內(nèi)的句號本身就失去了特殊含義。其他特殊字符也是如此,如加號 (+)。

要反轉(zhuǎn)一組字符,即表示要匹配除這組字符以外的任何字符,可以在開頭的括號后寫入一個護理符 (^)。

不止0和1。

國際字符

????????由于 JavaScript 最初的實現(xiàn)比較簡單,而且這種簡單的實現(xiàn)方式后來被固定為標準行為,因此 JavaScript 的正則表達式對于英語中沒有出現(xiàn)的字符非常遲鈍。例如,在 JavaScript 的正則表達式中,“單詞字符 ”僅指拉丁字母表中的 26 個字符(大寫或小寫)之一、十進制數(shù)字以及下劃線字符。像 é 或 β 這樣的字符肯定是單詞字符,但它們不會匹配 \w(而會匹配大寫字母 \W,即非單詞類別)。

????????一個奇怪的歷史巧合是,\s(空白)不存在這個問題,它可以匹配所有 Unicode 標準認為是空白的字符,包括非破折空格和蒙古語元音分隔符。

????????在正則表達式中使用 \p 可以匹配 Unicode 標準指定了特定屬性的所有字符。這樣,我們就能以一種更加國際化的方式匹配字母等字符。不過,同樣是出于與原始語言標準兼容的考慮,只有在正則表達式后面加上 u 字符(Unicode 標準)時,這些字符才能被識別。

\p{L} 任何字母字符 \p{N} 任何數(shù)字字符 \p{P} 任何標點符號 \P{L} 任何非字母(大寫 P 是反過來的) \p{Script=Hangul} 指定腳本中的任何字符(參見第 5 章)

????????使用 \w 進行文本處理可能需要處理非英語文本(甚至是包含 “cliché ”等借詞的英語文本),但這是一種負擔,因為它不會將 “é ”等字符視為字母。雖然 \p 屬性組比較啰嗦,但它們更強大。

????????另一方面,如果要對數(shù)字進行匹配以對其進行操作,通常需要對數(shù)字進行匹配,因為將任意數(shù)字字符轉(zhuǎn)換為 JavaScript 數(shù)字并不是 Number 這樣的函數(shù)所能完成的。

重復圖案的某些部分

????????我們現(xiàn)在知道了如何匹配一個數(shù)字。如果我們想匹配一個整數(shù)--一個或多個數(shù)字的序列,該怎么辦呢?

????????在正則表達式中,如果在某個元素后加上加號 (+),則表示該元素可能重復出現(xiàn)多次。因此,/\d+/ 可以匹配一個或多個數(shù)字字符。( 匹配 1 次或多次 )

????????星號 (*) 具有類似的含義,但也允許模式匹配零次。帶有星號的內(nèi)容永遠不會阻止模式匹配--如果找不到合適的文本匹配,它只會匹配零次。( 匹配 0 次或多次 )

????????問號(?)表示模式中的某個部分是可選的,這意味著它可能出現(xiàn)零次,也可能出現(xiàn)一次。在下面的示例中,u 字符是允許出現(xiàn)的,但當它缺失時,模式也會匹配:( 匹配 0 次或 1 次 )

????????要表示一個模式應出現(xiàn)的精確次數(shù),請使用大括號。例如,在一個元素后面加上{4},就要求該元素必須出現(xiàn)四次。也可以用這種方法指定一個范圍: {2,4}表示元素必須至少出現(xiàn)兩次,最多出現(xiàn)四次。

下面是日期和時間模式的另一個版本,它允許使用一位數(shù)和兩位數(shù)的日、月和小時。它也更容易解讀。

使用大括號時,也可以省略逗號后的數(shù)字,指定開放式范圍。例如,{5,} 表示五次或五次以上。

分組子表達式

????????要同時對多個元素使用 * 或 + 等運算符,必須使用括號。就后面的操作符而言,正則表達式中被括號括起來的部分算作一個元素。

第一個和第二個 + 字符分別只適用于 boo 和 hoo 中的第二個 o。第三個 + 字符適用于整組 (hoo+),可匹配一個或多個類似的序列。

示例中表達式末尾的 i 使該正則表達式不區(qū)分大小寫,可以匹配輸入字符串中的大寫 B,即使該模式本身是全小寫的。

匹配和分組

????????測試方法是匹配正則表達式的最簡單方法。它只會告訴你是否匹配,而不會告訴你其他信息。正則表達式還有一個 exec(執(zhí)行)方法,如果沒有找到匹配,該方法將返回空值,否則將返回一個包含匹配信息的對象。

????????exec 返回的對象有一個索引屬性,它告訴我們成功匹配的字符串從哪里開始。除此之外,該對象看起來像(實際上也是)一個字符串數(shù)組,其第一個元素是匹配成功的字符串。在前面的示例中,這就是我們要查找的數(shù)字序列。

字符串值也有類似的匹配方法。

????????當正則表達式包含用括號分組的子表達式時,與這些分組匹配的文本也會顯示在數(shù)組中。整個匹配總是第一個元素。下一個元素是與第一組(表達式中開頭括號在前的那一組)匹配的部分,然后是第二組,依此類推。

console.log(/(he)(ll)(o)/.exec("hello"));

輸出:

[

'hello',

'he',

'll',

'o',

index: 0,

input: 'hello',

groups: undefined

]

這句話的意思就是: 數(shù)組的第一個元素總是整個匹配的結(jié)果, 后續(xù)元素依次是每個分組匹配的內(nèi)容。

????????如果一個分組最終沒有被匹配(例如,后面跟了一個問號),那么它在輸出數(shù)組中的位置將保持未定義。當一個分組被多次匹配時(例如,后面有一個 +),只有最后一次匹配的分組才會出現(xiàn)在數(shù)組中。

console.log(/(\d)+/.exec('123'));//1-N

console.log(/(\d)*/.exec('123'));//0-N

console.log(/(\d)?/.exec('123'));//0-1

//輸出

[ '123', '3', index: 0, input: '123', groups: undefined ]//返回最后一個

[ '123', '3', index: 0, input: '123', groups: undefined ]//返回最后一個

[ '1', '1', index: 0, input: '123', groups: undefined ]//返回第一個

如果只想使用括號進行分組,而不想讓它們顯示在匹配數(shù)組中,可以在開頭的括號后加上?

(?:...):表示一個非捕獲組,它不會在結(jié)果中產(chǎn)生單獨的返回值。

組對于提取字符串的部分內(nèi)容非常有用。如果我們不僅要驗證字符串中是否包含日期,還要提取日期并構(gòu)建一個對象來表示日期,那么我們可以在數(shù)字模式周圍加上括號,然后直接從執(zhí)行結(jié)果中提取日期。

不過,我們首先要繞個彎,討論一下 JavaScript 中表示日期和時間值的內(nèi)置方法。

日期類

????????JavaScript 有一個標準的 Date 類,用于表示日期或時間點。只要使用 new 創(chuàng)建一個日期對象,就能得到當前的日期和時間。

您還可以為特定時間創(chuàng)建對象。

JavaScript 使用的慣例是,月號從 0 開始(因此 12 月是 11),而日號從 1 開始。這種做法既混亂又愚蠢。要小心。

最后四個參數(shù)(小時、分鐘、秒和毫秒)是可選的,如果沒有給出,則視為零。

時間戳以 UTC 時區(qū)自 1970 年開始的毫秒數(shù)存儲。這遵循了 “Unix 時間 ”的約定,“Unix 時間 ”是在那個時候發(fā)明的。1970 年之前的時間可以使用負數(shù)。日期對象上的 getTime 方法會返回這個數(shù)字??梢韵胂?,這個數(shù)字很大。

如果給 Date 構(gòu)造函數(shù)一個參數(shù),該參數(shù)將被視為毫秒計數(shù)。您可以通過創(chuàng)建一個新的 Date 對象并調(diào)用 getTime 或調(diào)用 Date.now 函數(shù)來獲取當前毫秒數(shù)。

Date 對象提供了 getFullYear、getMonth、getDate、getHours、getMinutes 和 getSeconds 等方法來提取其組成部分。除了 getFullYear 方法,還有 getYear 方法,它提供的是年份減去 1900(如 98 或 125)后的值,基本沒有什么用處。

在表達式中我們感興趣的部分加上括號,就可以從字符串中創(chuàng)建日期對象了。

下劃線 (_) 綁定將被忽略,僅用于跳過 exec 返回的數(shù)組中的完整匹配元素。

邊界和前瞻

????????不幸的是,getDate 也可以從字符串 “100-1-30000 ”中提取日期。匹配可能發(fā)生在字符串的任何地方,因此在這種情況下,它只會從第二個字符開始,到倒數(shù)第二個字符結(jié)束。

????????如果我們想強制要求匹配必須跨越整個字符串,可以添加標記符 ^ 和 $。 粗體符匹配輸入字符串的起點,而美元符號匹配輸入字符串的終點。因此,/^\d+$/ 會匹配完全由一個或多個數(shù)字組成的字符串,/^!/ 會匹配任何以感嘆號開頭的字符串,而 /x^/ 則不會匹配任何字符串(字符串開頭前不能有 x)。

????????還有一種 \b 標記用于匹配單詞邊界,即一邊是單詞字符,另一邊是非單詞字符的位置。遺憾的是,這些標記使用了和\w 一樣簡單的單詞字符概念,因此不是很可靠。

請注意,這些邊界標記并不匹配任何實際字符。它們只是強制執(zhí)行給定條件在模式中出現(xiàn)的位置成立。

????????前瞻測試也有類似的功能。它們提供了一個模式,如果輸入與該模式不匹配,就會導致匹配失敗,但實際上并不向前移動匹配位置。它們寫在 (?= 和) 之間。

來自GPT的解釋

邊界符號:^ 表示字符串的開始,$ 表示字符串的結(jié)束。因此,正則表達式 /^\d+$/ 意思是“匹配整個字符串必須完全由一個或多個數(shù)字組成”。例如,“123”會匹配,但“100-1-30000”不會,因為后者不是完全由數(shù)字構(gòu)成。\b 是單詞邊界,表示單詞字符(字母、數(shù)字或下劃線)和非單詞字符之間的邊界。比如,\bword\b 只會匹配“word”,而不會匹配“sword”或“wording”。前瞻(lookahead):前瞻用于檢查某個模式是否出現(xiàn)在當前匹配位置之后,但并不實際消耗字符。例如,(?=pattern) 會檢查后面是否有“pattern”,但不會將其包含在匹配結(jié)果中。比如,正則表達式 \d(?=abc) 會匹配后面跟著“abc”的數(shù)字,但匹配結(jié)果中不會包括“abc”。

第一個示例中的 e 是匹配所必需的,但不是匹配字符串的一部分。(?! ) 表示否定的前瞻性,第二個示例只匹配后面沒有空格的字符。

選擇模式

????????比方說,我們想知道一段文字中是否不僅包含一個數(shù)字,而且數(shù)字后面還包含豬、牛、雞中的一個單詞或它們的復數(shù)形式。

????????我們可以編寫三個正則表達式,然后依次測試它們,但有一個更好的方法。管道符 (|) 表示在左邊的模式和右邊的模式之間進行選擇。我們可以在這樣的表達式中使用它:

括號可用于限制管道運算符所適用的模式部分,您還可以將多個此類運算符放在一起,在兩個以上的備選方案中進行選擇。

匹配機制

????????從概念上講,當您使用 exec 或 test 時,正則表達式引擎會在字符串中尋找匹配項,首先嘗試從字符串的開頭開始匹配表達式,然后從第二個字符開始,依此類推,直到找到匹配項或到達字符串的末尾。它要么會返回能找到的第一個匹配項,要么根本找不到任何匹配項。

為了進行實際匹配,引擎會像處理流程圖一樣處理正則表達式。這是上例中家畜表達式的流程圖:

????????如果我們能找到一條從圖的左邊到右邊的路徑,那么我們的表達式就匹配了。我們在字符串中保留一個當前位置,每次移動經(jīng)過一個方框時,我們都要驗證當前位置后的字符串部分是否與該方框匹配。

回溯

????????正則表達式 /^([01]+b|[\da-f]+h|\d+)$/ 可以匹配后跟 b 的二進制數(shù)、后跟 h 的十六進制數(shù)(即 16 進制,字母 a 至 f 代表數(shù)字 10 至 15),或者不帶后綴字符的十進制數(shù)。這就是相應的圖表:

????????在匹配這個表達式時,即使輸入的內(nèi)容實際上并不包含二進制數(shù),也往往會輸入最上面的(二進制)分支。例如,在匹配字符串 “103 ”時,只有在匹配到 3 時才會發(fā)現(xiàn)我們進入了錯誤的分支。該字符串確實與表達式匹配,只是與我們當前所在的分支不匹配。

????????因此,匹配器會回溯。當進入一個分支時,它會記住當前位置(在本例中,位于字符串的起點,剛剛經(jīng)過圖中的第一個邊界框),這樣如果當前分支不成功,它就可以返回并嘗試另一個分支。對于字符串 “103”,在遇到 3 字符后,匹配器開始嘗試十六進制數(shù)字分支,但由于數(shù)字后面沒有 h,所以再次失敗。然后它又嘗試十進制數(shù)分支。這個分支符合要求,最終報告了一個匹配結(jié)果。

????????一旦發(fā)現(xiàn)完全匹配,匹配器就會停止。這意味著,如果有多個分支可能匹配一個字符串,則只使用第一個分支(按分支在正則表達式中出現(xiàn)的位置排序)。

????????回溯也會發(fā)生在 + 和 * 等重復運算符上。如果將 /^.*x/ 與 “abcxe ”匹配,.* 部分將首先嘗試使用整個字符串。然后,引擎會意識到它需要一個 x 來匹配該模式。由于字符串末尾沒有 x,星形運算符會嘗試匹配少一個字符。但是,匹配器在 abcx 之后也沒有找到 x,因此它再次回溯,將星形運算符匹配到 abc?,F(xiàn)在,它在需要的地方找到了一個 x,并報告從 0 到 4 位置的匹配成功。

????????正則表達式可以進行大量的回溯。當一個模式能以多種不同的方式匹配一段輸入時,就會出現(xiàn)這個問題。例如,如果我們在編寫二進制正則表達式時感到困惑,可能會不小心寫成 /([01]+)+b/ 這樣的表達式。

????????如果試圖匹配一長串沒有尾部 b 字符的 0 和 1,匹配器會先通過內(nèi)循環(huán),直到用完所有數(shù)字。然后,它注意到?jīng)]有 b,于是回退一個位置,通過一次外循環(huán),然后再次放棄,試圖再次從內(nèi)循環(huán)中回退。它將繼續(xù)嘗試通過這兩個循環(huán)的所有可能路徑。這意味著每增加一個字符,工作量就會增加一倍。即使只有幾十個字符,匹配也會耗費很長時間。

替換法

字符串值有一個 replace 方法,可用于用另一個字符串替換部分字符串。

第一個參數(shù)也可以是正則表達式,在這種情況下,正則表達式的第一個匹配項將被替換。如果在正則表達式后添加 g 選項(表示全局),字符串中的所有匹配都會被替換,而不僅僅是第一個匹配。

將正則表達式與替換結(jié)合使用的真正優(yōu)勢在于,我們可以在替換字符串中引用匹配的組。例如,我們有一個包含人名的大字符串,每行一個人名,格式為 Lastname, Firstname。如果我們想交換這些名字并去掉逗號,以獲得 Firstname Lastname 格式,我們可以使用下面的代碼:

替換字符串中的 $1 和 $2 指的是模式中的括號組。$1替換為與第一組匹配的文本,$2替換為與第二組匹配的文本,依此類推,直至 $9。

替換的第二個參數(shù)可以是函數(shù),而不是字符串。每次替換時,都會調(diào)用函數(shù),并將匹配組(以及整個匹配)作為參數(shù),然后將函數(shù)的返回值插入新字符串。

這里有一個例子:

這段代碼接收一個字符串,查找所有出現(xiàn)的數(shù)字后跟字母數(shù)字單詞,然后返回一個字符串,該字符串中的每一個數(shù)字都少一個。

(\d+) 組最終作為函數(shù)的金額參數(shù),而 (\p{L}+) 組則與單位綁定。函數(shù)會將 amount 轉(zhuǎn)換為數(shù)字--這總是有效的,因為它之前匹配了 \d+,并在只剩下一個或零的情況下做了一些調(diào)整。

貪婪

????????我們可以使用 replace 來編寫一個函數(shù),刪除 JavaScript 代碼中的所有注釋。下面是第一次嘗試:

????????操作符 | 之前的部分匹配兩個斜線字符,后面是任意數(shù)量的非新行字符。多行注釋的部分涉及的內(nèi)容更多。我們使用 [^](不在空字符集中的任何字符)來匹配任何字符。這里我們不能只使用句號,因為塊注釋可以在新行中繼續(xù),而句號字符不能匹配換行符。

但最后一行的輸出似乎出了問題。為什么呢?

????????正如我在 “回溯 ”一節(jié)中所述,表達式的 [^]* 部分將首先盡可能多地匹配。如果這導致模式的下一部分失敗,匹配器就會向后移動一個字符,然后從那里重新開始匹配。在示例中,匹配器首先嘗試匹配整個字符串的其余部分,然后從這里開始向后移動。在后退 4 個字符后,它會找到 */ 的出現(xiàn)并進行匹配。這并不是我們想要的結(jié)果--我們的目的是匹配單個注釋,而不是一直匹配到代碼末尾,找到最后一個注釋塊的末尾。

????????由于這種行為,我們說重復運算符(+、*、?和 {})是貪婪的,這意味著它們會盡可能多地匹配,并從那里開始回溯。如果在它們后面加上問號(+?, *?, ??, {}?),它們就會變得不貪心,開始時盡可能少匹配,只有當剩余的模式不適合較小的匹配時,才會匹配更多。

????????在這種情況下,這正是我們想要的。通過讓星號匹配到 */ 的最小字符段,我們只消耗了一個注釋塊,而沒有更多。

正則表達式程序中的許多錯誤都可以追溯到無意中使用了貪婪運算符,而非貪婪運算符的效果會更好。在使用重復運算符時,應首選非貪婪變體。

動態(tài)創(chuàng)建 RegExp 對象

????????在某些情況下,您在編寫代碼時可能不知道需要匹配的確切模式。例如,您想測試一段文本中的用戶姓名。您可以創(chuàng)建一個字符串,然后使用 RegExp 構(gòu)造函數(shù)。

在創(chuàng)建字符串中的\s 部分時,我們必須使用兩個反斜線,因為我們是將它們寫入普通字符串,而不是斜線包圍的正則表達式。RegExp 構(gòu)造函數(shù)的第二個參數(shù)包含正則表達式的選項,在本例中,“gi ”表示全局和大小寫不敏感。

但如果用戶的名字是 “dea+hl[]rd ”呢?這樣就會產(chǎn)生一個毫無意義的正則表達式,實際上無法匹配用戶的姓名。

為了解決這個問題,我們可以在任何具有特殊含義的字符前添加反斜線。

搜索方法

????????雖然字符串的 indexOf 方法不能使用正則表達式調(diào)用,但另一種方法 search 可以使用正則表達式。和 indexOf 一樣,它也會返回找到正則表達式的第一個索引,如果沒有找到,則返回-1。

遺憾的是,我們無法指出匹配應從給定的偏移量開始(就像我們可以使用 indexOf 的第二個參數(shù)一樣),而這通常是有用的。

lastIndex 屬性

????????exec方法同樣沒有提供從字符串中給定位置開始搜索的便捷方法。但它提供了一種不方便的方法。

????????正則表達式對象具有屬性。其中一個屬性是 source,它包含創(chuàng)建表達式的字符串。另一個屬性是 lastIndex,在某些有限的情況下,它控制著下一個匹配將從哪里開始。

????????在這些情況下,正則表達式必須啟用全局(g)或粘性(y)選項,并且必須通過執(zhí)行方法進行匹配。同樣,如果能允許向 exec 傳遞一個額外的參數(shù),就可以減少混亂,但混亂是 JavaScript 正則表達式接口的一個基本特征。

????????如果匹配成功,exec 調(diào)用會自動更新 lastIndex 屬性,使其指向匹配結(jié)果之后(+1)。如果沒有找到匹配結(jié)果,lastIndex 將被設回 0,這也是它在新構(gòu)建的正則表達式對象中的值。

????????全局選項和粘性選項的區(qū)別在于,啟用粘性選項后,只有直接從 lastIndex 開始,匹配才會成功,而啟用全局選項后,匹配會提前搜索可以開始匹配的位置。(lastIndex表示開始搜索的位置)

????????在多個執(zhí)行調(diào)用中使用共享的正則表達式值時,這些對 lastIndex 屬性的自動更新可能會導致問題。你的正則表達式可能會意外地從上一次調(diào)用留下的索引開始。

????????全局選項的另一個有趣作用是改變了字符串匹配方法的工作方式。當使用全局表達式調(diào)用時,match 不會返回一個類似于 exec 所返回的數(shù)組,而是會查找字符串中所有與模式匹配的字符串,并返回一個包含匹配字符串的數(shù)組。

因此,請謹慎使用全局正則表達式。在需要使用全局正則表達式的情況下--調(diào)用替換和需要顯式使用 lastIndex 的地方--通常需要使用全局正則表達式。

常見的做法是在字符串中查找正則表達式的所有匹配項。我們可以使用 matchAll 方法來實現(xiàn)這一目的。

此方法返回一個匹配數(shù)組。為 matchAll 提供的正則表達式必須啟用 g。

解析 INI 文件

????????在本章的最后,我們將討論一個需要使用正則表達式的問題。想象一下,我們正在編寫一個程序,從互聯(lián)網(wǎng)上自動收集敵人的信息。(在這里,我們不會實際編寫該程序,而只是編寫讀取配置文件的部分。對不起)。配置文件看起來是這樣的

這種格式是一種廣泛使用的文件格式,通常稱為 INI 文件,其具體規(guī)則如下:

空行和以分號開頭的行將被忽略。以[]包裝的行開始一個新的部分。包含字母數(shù)字標識符和 = 字符的行在當前部分添加一個設置。其他均無效。

????????我們的任務是將這樣一個字符串轉(zhuǎn)換成一個對象,該對象的屬性包含寫在第一個章節(jié)標題之前的設置字符串和章節(jié)的子對象,這些子對象包含章節(jié)的設置。

????????由于格式必須逐行處理,因此將文件分割成不同行是一個好的開始。我們在第 4 章中看到了分割方法。不過,有些操作系統(tǒng)不僅使用換行符來分行,還使用換行后的回車符(“\r\n”)。鑒于 split 方法也允許使用正則表達式作為其參數(shù),我們可以使用類似 /\r?\n/ 這樣的正則表達式來分割,這樣就可以在行間同時使用“\n ”和“\r\n”。

????????代碼會遍歷文件的每一行,并建立一個對象。頂部的屬性直接存儲在該對象中,而章節(jié)中的屬性則存儲在單獨的章節(jié)對象中。章節(jié)綁定指向當前章節(jié)的對象。

????????有兩種重要的行--節(jié)標題行或?qū)傩孕小.斠恍惺浅R?guī)屬性時,它被存儲在當前節(jié)中。如果是節(jié)標題,則會創(chuàng)建一個新的節(jié)對象,并將節(jié)設置為指向它。

????????注意反復使用 ^ 和 $ 是為了確保表達式匹配整行,而不僅僅是其中的一部分。如果不使用這兩種表達式,代碼在大多數(shù)情況下都能正常工作,但在某些輸入情況下卻會出現(xiàn)奇怪的行為,這可能是一個難以追蹤的錯誤。

????????if (match = string.match(...))模式利用了賦值表達式 (=) 的值就是賦值這一事實。我們通常無法確定對 match 的調(diào)用是否會成功,因此只能在 if 語句中測試這一點,才能訪問結(jié)果對象。為了不破壞令人愉快的 else if 表單鏈,我們將匹配的結(jié)果賦值給一個綁定,并立即使用該賦值作為 if 語句的測試。

????????如果一行不是章節(jié)標題或?qū)傩?,函?shù)會使用表達式 /^\s*(;|$)/ 檢查它是注釋還是空行,以匹配只包含空白或空白后有分號(使行的其余部分成為注釋)的行。如果一行不符合任何預期形式,函數(shù)就會拋出異常。

代碼單位和字符

????????JavaScript 正則表達式中的另一個標準化設計錯誤是,在默認情況下,. 或 ? 等運算符的作用對象是代碼單元(如第 5 章所述),而不是實際字符。這意味著由兩個代碼單元組成的字符會表現(xiàn)得很奇怪。

問題在于第一行中的“? ”被視為兩個代碼單元,而{3}只應用于第二個單元。同樣,圓點匹配的是一個代碼單 元,而不是組成玫瑰表情符號的兩個代碼單元。

您必須在正則表達式中添加 u(Unicode)選項,以使其正確處理此類字符。

總結(jié)

正則表達式是表示字符串模式的對象。它們使用自己的語言來表達這些模式。

/abc/ 字符序列

/[abc]/ 一組字符中的任何字符

/[^abc]/ 不在字符集中的任何字符

/[0-9]/ 字符范圍內(nèi)的任何字符

/x+/ 模式 x 的一次或多次出現(xiàn)

/x+?/ 一次或多次出現(xiàn),無冗余

/x*/ 零次或多次出現(xiàn)

/x?/ 零次或一次出現(xiàn)

/x{2,4}/ 出現(xiàn) 2 到 4 次

/(abc)/ 一組

/a|b|c/ 幾種模式中的任意一種

/d/ 任何數(shù)字字符

/w/ 字母數(shù)字字符("單詞字符)

/s/ 任何空白字符

/./ 除換行符外的任何字符

/\ 任何字母字符

/^/ 輸入開始

/$/ 輸入結(jié)束

/(?=a)/ 前瞻性測試

????????正則表達式有一個 test 方法,用于測試給定字符串是否與之匹配。正則表達式還有一個 exec 方法,當找到匹配時,它會返回一個包含所有匹配組的數(shù)組。該數(shù)組有一個索引屬性,表示匹配從哪里開始。

????????字符串有一個 match 方法,用于與正則表達式匹配,還有一個 search 方法,用于搜索正則表達式,只返回匹配的起始位置。它們的 replace 方法可以用替換字符串或函數(shù)替換與模式匹配的字符串。

????????正則表達式可以有選項,選項寫在斜線后。i 選項使匹配不區(qū)分大小寫。g 選項使表達式成為全局表達式,除其他外,這將導致 replace 方法替換所有實例,而不僅僅是第一個實例。y 選項使表達式具有粘性,這意味著在查找匹配時,它不會向前搜索和跳過字符串的一部分。u 選項開啟了 Unicode 模式,啟用了 \p 語法,并修復了處理占用兩個代碼單元的字符時出現(xiàn)的一些問題。

????????正則表達式是一種鋒利的工具,但使用起來并不方便。正則表達式極大地簡化了某些任務,但在應用于復雜問題時,很快就會變得難以駕馭。要知道如何使用正則表達式,部分工作就是要克制自己的沖動,不要把正則表達式無法表達的東西硬塞進正則表達式中。

練習

????????在進行這些練習的過程中,你幾乎不可避免地會對某些正則表達式莫名其妙的行為感到困惑和沮喪。有時,將正則表達式輸入到 debuggex.com 等在線工具中,看看它的可視化是否符合你的意圖,并嘗試它對各種輸入字符串的響應方式,會對你有所幫助。

Regexp 高爾夫

????????代碼高爾夫是指用盡可能少的字符來表達特定程序的游戲。同樣,“正則表達式高爾夫 ”也是指編寫盡可能少的正則表達式來匹配給定的模式,而且只能匹配該模式。

????????請為下列每個項目編寫一個正則表達式,以測試給定模式是否出現(xiàn)在字符串中。正則表達式應只匹配包含該模式的字符串。當您的表達式有效時,看看是否可以將其變得更小。

規(guī)則要求:

car 和 catpop 和 propferret,ferry和ferrari任何以 ious 結(jié)尾的單詞空白字符,后面跟句號、逗號、冒號或分號超過6個字母的單詞沒有字母 e(或 E)的單詞

請參考本章摘要中的表格以獲得幫助。用幾個測試字符串測試每個解決方案。

// Fill in the regular expressions

verify(/.../,

["my car", "bad cats"],

["camper", "high art"]);

verify(/.../,

["pop culture", "mad props"],

["plop", "prrrop"]);

verify(/.../,

["ferret", "ferry", "ferrari"],

["ferrum", "transfer A"]);

verify(/.../,

["how delicious", "spacious room"],

["ruinous", "consciousness"]);

verify(/.../,

["bad punctuation ."],

["escape the period"]);

verify(/.../,

["Siebentausenddreihundertzweiundzwanzig"],

["no", "three small words"]);

verify(/.../,

["red platypus", "wobbling nest"],

["earth bed", "bedr?vet abe", "BEET"]);

function verify(regexp, yes, no) {

// Ignore unfinished exercises

if (regexp.source == "...") return;

for (let str of yes) if (!regexp.test(str)) {

console.log(`Failure to match '${str}'`);

}

for (let str of no) if (regexp.test(str)) {

console.log(`Unexpected match for '${str}'`);

}

}

答案:

verify(/(car|cat)/, ["my car", "bad cats"], ["camper", "hight art"]);

verify(/(pop|prop)/,["pop culture", "mad props"],["plop", "prrrop"]);

verify(/(ferret|ferry|ferrari)/,["ferret", "ferry", "ferrari"],["ferrum", "transfer A"]);

verify(/\b\w*ious\b/,["how delicious", "spacious room"],["ruinous", "consciousness"]);

verify(/\b\s(.|;|:|,)\b/, ["bad punctuation ."], ["escape the period"]);

verify(/\b\w{6,}\b/, ["Siebentausenddreihundertzweiundzwanzig"], ["no", "three small words"]);

verify(/\b(?!\w*e)(?!\w*E)\w+\b/, ["red platypus", "wobbling nest"], ["earth bed", "bedr?vet abe", "BEET"]);

柚子快報激活碼778899分享:mysql 9. 正則表達式

http://yzkb.51969.com/

好文推薦

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權,聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19585511.html

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄