2020 年 2 月 29 日

量詞 +, *, ? 和 {n}

假設我們有一個像 +7(903)-123-45-67 的字串,並想要找出其中的所有數字。但與之前不同的是,我們感興趣的不是單獨的數字,而是完整的數字:7, 903, 123, 45, 67

數字是一個或多個數字 \d 的序列。為了標示我們需要多少個,我們可以附加一個量詞

數量 {n}

最簡單的量詞是使用大括號括起來的數字:{n}

量詞附加在一個字元(或字元類別,或 [...] 集合等)之後,並指定我們需要多少個。

它有幾個進階形式,我們來看一些範例

精確計數:{5}

\d{5} 表示精確的 5 個數字,與 \d\d\d\d\d 相同。

以下範例尋找 5 位數

alert( "I'm 12345 years old".match(/\d{5}/) ); //  "12345"

我們可以加入 \b 排除較長的數字:\b\d{5}\b

範圍:{3,5},比對 3-5 次

若要尋找 3 到 5 位數,我們可以將限制放入大括弧中:\d{3,5}

alert( "I'm not 12, but 1234 years old".match(/\d{3,5}/) ); // "1234"

我們可以省略上限。

然後正規表示法 \d{3,} 尋找長度為 3 或以上的數字序列

alert( "I'm not 12, but 345678 years old".match(/\d{3,}/) ); // "345678"

讓我們回到字串 +7(903)-123-45-67

數字是一連串一個或多個數字。因此正規表示法為 \d{1,}

let str = "+7(903)-123-45-67";

let numbers = str.match(/\d{1,}/g);

alert(numbers); // 7,903,123,45,67

簡寫

對於大多數使用的量詞,都有簡寫。

+

表示「一個或多個」,與 {1,} 相同。

例如,\d+ 尋找數字

let str = "+7(903)-123-45-67";

alert( str.match(/\d+/g) ); // 7,903,123,45,67
?

表示「零個或一個」,與 {0,1} 相同。換句話說,它使符號為選用。

例如,樣式 ou?r 尋找 o 後接零個或一個 u,然後是 r

因此,colou?r 找到 colorcolour

let str = "Should I write color or colour?";

alert( str.match(/colou?r/g) ); // color, colour
*

表示「零個或多個」,與 {0,} 相同。也就是說,字元可以重複多次或不存在。

例如,\d0* 尋找一個數字後接任意數量的零(可以很多或沒有)

alert( "100 10 1".match(/\d0*/g) ); // 100, 10, 1

將其與 +(一個或多個)比較

alert( "100 10 1".match(/\d0+/g) ); // 100, 10
// 1 not matched, as 0+ requires at least one zero

更多範例

量詞使用非常頻繁。它們是複雜正規表示法的「建構區塊」,因此讓我們看看更多範例。

十進位小數(浮點數)的正規表示法:\d+\.\d+

實際運用

alert( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // 12.345

「不帶屬性的開啟 HTML 標籤」的正規表示法,例如 <span><p>

  1. 最簡單的:/<[a-z]+>/i

    alert( "<body> ... </body>".match(/<[a-z]+>/gi) ); // <body>

    正規表示法尋找字元 '<' 後接一個或多個拉丁字母,然後是 '>'

  2. 改良版:/<[a-z][a-z0-9]*>/i

    根據標準,HTML 標籤名稱可以在除了第一個位置以外的任何位置有數字,例如 <h1>

    alert( "<h1>Hi!</h1>".match(/<[a-z][a-z0-9]*>/gi) ); // <h1>

正規表示法「不帶屬性的開啟或關閉 HTML 標籤」:/<\/?[a-z][a-z0-9]*>/i

我們在樣式的開頭附近加入一個選用的斜線 /?。必須使用反斜線來跳脫它,否則 JavaScript 會認為它是樣式的結尾。

alert( "<h1>Hi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1>
為了讓正規表示法更精確,我們通常需要讓它更複雜

我們可以在這些範例中看到一個常見的規則:正規表示法越精確,它就越長且越複雜。

例如,對於 HTML 標籤,我們可以使用一個更簡單的正規表示法:<\w+>。但由於 HTML 對標籤名稱有更嚴格的限制,<[a-z][a-z0-9]*> 較為可靠。

我們可以使用 <\w+> 還是需要 <[a-z][a-z0-9]*>

在實際情況中,這兩種變體都是可以接受的。這取決於我們對「額外」比對的容忍度,以及是否難以使用其他方法從結果中移除它們。

任務

重要性:5

建立一個正規表示法來尋找省略號:3 個(或更多?)點連續出現。

檢查它

let regexp = /your regexp/g;
alert( "Hello!... How goes?.....".match(regexp) ); // ..., .....

解決方案

let regexp = /\.{3,}/g;
alert( "Hello!... How goes?.....".match(regexp) ); // ..., .....

請注意,點是一個特殊字元,所以我們必須跳脫它並插入為 \.

建立一個正規表示法來搜尋寫成 #ABCDEF 的 HTML 顏色:第一個是 #,然後是 6 個十六進位字元。

使用範例

let regexp = /...your regexp.../

let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2 #12345678";

alert( str.match(regexp) )  // #121212,#AA00ef

附註:在這個任務中,我們不需要其他顏色格式,例如 #123rgb(1,2,3) 等。

我們需要尋找 # 後面接著 6 個十六進位字元。

十六進位字元可以用 [0-9a-fA-F] 來描述。或者,如果我們使用 i 旗標,則只需 [0-9a-f]

然後,我們可以使用量詞 {6} 來尋找 6 個這樣的字元。

因此,我們有正規表示法:/#[a-f0-9]{6}/gi

let regexp = /#[a-f0-9]{6}/gi;

let str = "color:#121212; background-color:#AA00ef bad-colors:f#fddee #fd2"

alert( str.match(regexp) );  // #121212,#AA00ef

問題在於它會在較長的序列中找到顏色

alert( "#12345678".match( /#[a-f0-9]{6}/gi ) ) // #123456

為了修正這個問題,我們可以在結尾加上 \b

// color
alert( "#123456".match( /#[a-f0-9]{6}\b/gi ) ); // #123456

// not a color
alert( "#12345678".match( /#[a-f0-9]{6}\b/gi ) ); // null
教學課程地圖

留言

在留言前請先閱讀…
  • 如果您有改進建議 - 請 提交 GitHub 議題 或提交拉取請求,而不是留言。
  • 如果您無法理解文章中的內容 – 請詳細說明。
  • 要插入幾行程式碼,請使用 <code> 標籤,對於多行程式碼 – 請用 <pre> 標籤包覆,對於超過 10 行的程式碼 – 請使用沙盒 (plnkrjsbincodepen…)