Javascript 選擇 (OR) |

2023-02-17 11:02 更新

選擇是正則表達(dá)式中的一個(gè)術(shù)語,實(shí)際上是一個(gè)簡單的“或”。

在正則表達(dá)式中,它用豎線 | 表示。

例如,我們想要找出編程語言:HTML、PHP、Java 或 JavaScript。

對(duì)應(yīng)的正則表達(dá)式為:html|php|java(script)?。

用例如下:

let regexp = /html|php|css|java(script)?/gi;

let str = "First HTML appeared, then CSS, then JavaScript";

alert( str.match(regexp) ); // 'HTML', 'CSS', 'JavaScript'

我們看到過類似的東西 —— 方括號(hào)。它允許我們在多個(gè)字符中進(jìn)行選擇,例如 gr[ae]y 匹配 gray 或 grey。

方括號(hào)只允許字符或字符類。選擇允許任何表達(dá)式。正則表達(dá)式 A|B|C 表示表達(dá)式 A、B 或 C 其一均可。

例如:

  • ?gr(a|e)y? 等同于 ?gr[ae]y?。
  • ?gra|ey? 表示 ?gra? 或 ?ey?。

要將選擇應(yīng)用于模式中一部分內(nèi)容的選擇,我們可以將其括在括號(hào)中:

  • I love HTML|CSS 匹配 I love HTMLCSS。
  • I love (HTML|CSS) 匹配 I love HTMLI love CSS

示例:用于時(shí)間匹配的正則表達(dá)式

在之前的章節(jié)中有個(gè)任務(wù)是構(gòu)建用于查找形如 hh:mm 的時(shí)間字符串,例如 12:00。但是簡單的 \d\d:\d\d 太模糊了。它也會(huì)匹配 25:99(因?yàn)?25 和 99 都與模式匹配,但這不是有效的時(shí)間)。

如何構(gòu)建更好的模式?

我們可以應(yīng)用更精細(xì)的匹配。首先,對(duì)于時(shí)間:

  • 如果第一位數(shù)是 01,那么下一位數(shù)可以是任何數(shù)值:[01]\d。
  • 否則,如果第一位數(shù)是 2,那么下一位數(shù)必須是 [0-3]。
  • 不允許其他的首位數(shù)。

我們可以使用選擇在正則表達(dá)式中編寫這兩種變體:[01]\d|2[0-3]。

接下來,分鐘必須為從 00 到 59 的數(shù)。寫成正則表達(dá)式即為 [0-5]\d:第一個(gè)數(shù)字 0-5,然后是任何數(shù)字。

如果我們將小時(shí)和分鐘的正則表達(dá)式組合在一起,我們會(huì)得到:[01]\d|2[0-3]:[0-5]\d

我們差不多完成了,但有一個(gè)問題。選擇 | 現(xiàn)在恰好位于 [01]\d 和 2[0-3]:[0-5]\d 之間。

也就是說:它只匹配符號(hào)左側(cè)或右側(cè)任一表達(dá)式。

[01]\d  |  2[0-3]:[0-5]\d

此模式查找 [01]\d 或 2[0-3]:[0-5]\d。

但這是錯(cuò)誤的,應(yīng)該只在正則表達(dá)式的“小時(shí)”部分使用選擇,以允許 [01]\d 或 2[0-3]。讓我們通過將“小時(shí)”括在括號(hào)中來糾正這個(gè)問題:([01]\d|2[0-3]):[0-5]\d

最終的解決方案:

let regexp = /([01]\d|2[0-3]):[0-5]\d/g;

alert("00:00 10:10 23:59 25:99 1:2".match(regexp)); // 00:00,10:10,23:59

任務(wù)


查找編程語言

有很多編程語言,例如 Java、JavaScript、PHP、C 或 C++。

構(gòu)建一個(gè)正則表達(dá)式,用來匹配字符串 Java JavaScript PHP C++ C 中包含的編程語言:

let regexp = /你的正則表達(dá)式/g;

alert("Java JavaScript PHP C++ C".match(regexp)); // Java JavaScript PHP C++ C

解決方案

首先想到的解法是列出所有編程語言,在它們之間加上 | 符號(hào)。

但運(yùn)行結(jié)果不符合預(yù)期:

let regexp = /Java|JavaScript|PHP|C|C\+\+/g;

let str = "Java, JavaScript, PHP, C, C++";

alert( str.match(regexp) ); // Java,Java,PHP,C,C

正則表達(dá)式引擎注意查找選擇。也就是說:它先檢查是否存在 Java,不存在 —— 接著匹配 JavaScript 及其后的字符串。

結(jié)果,JavaScript 永遠(yuǎn)匹配不到,因?yàn)?nbsp;Java 先被匹配了。

C 和 C++ 同理。

這個(gè)問題有兩個(gè)解決方式:

  1. 更改順序以先檢查較長的匹配項(xiàng):?JavaScript|Java|C\+\+|C|PHP?。
  2. 合并相同前綴:?Java(Script)?|C(\+\+)?|PHP?。

測試一下:

let regexp = /Java(Script)?|C(\+\+)?|PHP/g;

let str = "Java, JavaScript, PHP, C, C++";

alert( str.match(regexp) ); // Java,JavaScript,PHP,C,C++

查找 bbtag 對(duì)

“bb-tag” 形如 [tag]...[/tag]tag 匹配 b、url 或 quote 中之一。

例如:

[b]text[/b]
[url]http://google.com[/url]

BB-tags 可以嵌套。但標(biāo)簽不能自嵌套,比如:

可以:
[url] [b]http://google.com[/b] [/url]
[quote] [b]text[/b] [/quote]

不可以:
[b][b]text[/b][/b]

標(biāo)簽可以包含換行,通常:

[quote]
  [b]text[/b]
[/quote]

構(gòu)造一個(gè)正則表達(dá)式用于查找所有 BB-tags 及其內(nèi)容。

例如:

let regexp = /your regexp/flags;

let str = "..[url]http://google.com[/url]..";
alert( str.match(regexp) ); // [url]http://google.com[/url]

如果標(biāo)簽嵌套,那么我們需要記錄匹配的外層標(biāo)簽(如果需要,我們可以繼續(xù)在其內(nèi)容中搜索):

let regexp = /你的正則表達(dá)式/flags;

let str = "..[url][b]http://google.com[/b][/url]..";
alert( str.match(regexp) ); // [url][b]http://google.com[/b][/url]

解決方案

起始標(biāo)簽是 \[(b|url|quote)\]。

匹配字符串直到遇到結(jié)束標(biāo)簽 —— 讓我們使用模式 .*? 和修飾符 s 來匹配包括換行符在內(nèi)的任何字符,然后向結(jié)束標(biāo)簽添加反向引用。

完整模式為:\[(b|url|quote)\].*?\[/\1]

代碼運(yùn)行如下:

let regexp = /\[(b|url|quote)].*?\[\/\1]/gs;

let str = `
  [b]hello![/b]
  [quote]
    [url]http://google.com[/url]
  [/quote]
`;

alert( str.match(regexp) ); // [b]hello![/b],[quote][url]http://google.com[/url][/quote]

請(qǐng)注意,除了轉(zhuǎn)義 [ 之外,我們還必須為結(jié)束標(biāo)簽 [\/\1] 轉(zhuǎn)義一個(gè)斜線,因?yàn)橥ǔP本€會(huì)關(guān)閉模式。


查找引用的字符串

構(gòu)建一個(gè)正則表達(dá)式以查找雙引號(hào) ?"..."? 中的字符串。

字符串應(yīng)該支持轉(zhuǎn)義,就像 JavaScript 字符串一樣。例如,引號(hào)可以插入為 \",換行符可以插入為 \n,而反斜線本身可以插入為 \\。

let str = "Just like \"here\".";

請(qǐng)注意,轉(zhuǎn)義的引號(hào) \" 不會(huì)結(jié)束字符串匹配。

所以,我們應(yīng)該匹配兩個(gè)引號(hào)之間的內(nèi)容,且忽略中間轉(zhuǎn)義的引號(hào)。

這是任務(wù)的基本部分,否則這個(gè)任務(wù)就沒什么意思了。

要匹配的字符串示例:

.. "test me" ..
.. "Say \"Hello\"!" ..(其中有被轉(zhuǎn)義的引號(hào))
.. "\\" ..(其中有雙反斜線)
.. "\\ \"" ..(其中有雙反斜線和被轉(zhuǎn)義的引號(hào))

在 JavaScript 中,雙反斜線用于把反斜線轉(zhuǎn)義為字符串,如下所示:

let str = ' .. "test me" .. "Say \\"Hello\\"!" .. "\\\\ \\"" .. ';

// 存儲(chǔ)中的字符串
alert(str); //  .. "test me" .. "Say \"Hello\"!" .. "\\ \"" ..

解決方案

解決方案:/"(\\.|[^"\\])*"/g。

一步一步來分析一下:

  • 首先匹配左雙引號(hào) "
  • 接著如果有反斜線 \\,則匹配其后跟隨的任意字符(.)。(技術(shù)上,我們必須在模式中用雙反斜線,因?yàn)樗且粋€(gè)特殊的字符,但實(shí)際上是一個(gè)反斜線字符)。
  • 如果沒有,則匹配除雙引號(hào)(表示字符串的末尾)和反斜線(排除僅存在反斜杠的情況,反斜杠僅在和其后字符一起使用時(shí)有效)外的任何字符:[^"\\]。
  • ……繼續(xù)匹配直到遇到右雙引號(hào)

代碼運(yùn)行如下:

let regexp = /"(\\.|[^"\\])*"/g;
let str = ' .. "test me" .. "Say \\"Hello\\"!" .. "\\\\ \\"" .. ';

alert( str.match(regexp) ); // "test me","Say \"Hello\"!","\\ \""

查找完整標(biāo)簽

寫出一個(gè)正則表達(dá)式,用于查找 <style...> 標(biāo)簽。它應(yīng)該匹配完整的標(biāo)簽:該標(biāo)簽可能沒有特性(attributes)<style>,也可能有很多特性 <style type="..." id="...">。

……同時(shí)正則表達(dá)式不應(yīng)該匹配 <styler>

例如:

let regexp = /你的正則表達(dá)式/g;

alert( '<style> <styler> <style test="...">'.match(regexp) ); // <style>, <style test="...">

解決方案

模式的開頭很明顯:<style。

……但我們不能簡單地將表達(dá)式寫為 <style.*?>,因?yàn)闀?huì)匹配上 <styler>。

我們要匹配的是在 <style 之后緊跟著一個(gè)空格然后是可選的其他內(nèi)容,或者直接是閉標(biāo)簽 >。

寫成正則表達(dá)式即為:<style(>|\s.*?>)

代碼運(yùn)行如下:

let regexp = /<style(>|\s.*?>)/g;

alert( '<style> <styler> <style test="...">'.match(regexp) ); // <style>, <style test="...">


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)