iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
1
Modern Web

JavaScript 之旅系列 第 9

JavaScript 之旅 (9):RegExp 的 s (dotAll) flag

  • 分享至 

  • xImage
  •  

本篇介紹 ES2018 (ES9) 提供的 RegExp 的 s (dotAll) flag。

本篇會有很多特殊字元,但 IT 鐵人這裡無法顯示這些字元,所以內文會看到大量的「???」XDD

過去的問題

. 在 RegExp 中的限制

在 RegExp (regular expression,正規表達式,正規表示式) pattern 中,. (點) 可用來 match 單一的任何字元,但在 ECMAScript 有兩個例外:

  • . 與 astral (即非 BMP) 字元不 match
  • . 與 line terminator 字元不 match

. 與非 BMP 字元不 match

. 與 astral (即非 BMP) 字元不 match,像我們常見的 emoji 就是這種字元,以「 」為例:

/^.$/.test('?');
// false

但這個問題可用 u ( unicode ) flag 來解決:

/^.$/u.test('?');
// true

註:對 ECMAScript 來說,BMP 字元就是一個字元為一個 code point,而其他非 BMP 的字元就是兩個字元,因為這些字元是兩個 code point,只要該字元是幾個 code point,就是 length 幾。例如:

'?'.length;
// 2

'\uD83D\uDE0E' === '?';
// true

. 與 line terminator 字元不 match

line terminator 字元不與 . match,常見的有 \n\r

/^.$/.test('\n');
// false

/^.$/.test('\r');
// false

下面是在 spec 中對 line terminator 的定義:

  • U+000A:LINE FEED (LF) ( \n )
  • U+000D:CARRIAGE RETURN (CR) ( \r )
  • U+2028:LINE SEPARATOR
  • U+2029:PARAGRAPH SEPARATOR

而下面在 spec 中對 white space 的定義:

  • U+0009:CHARACTER TABULATION
  • U+000B:LINE TABULATION ( \v )
  • U+000C:FORM FEED (FF) ( \f )
  • U+0020:SPACE
  • U+00A0:NO-BREAK SPACE
  • U+FEFF:ZERO WIDTH NO-BREAK SPACE
  • ...

但有時會根據情況,會將一些字元視為換行字元,例如:

  • U+000B:LINE TABULATION ( \v )
  • U+000C:FORM FEED (FF) ( \f )
  • U+0085:NEXT LINE

這就會讓 RegExp pattern 中的 . 發生一些問題:

  • . 不包含某些 newline 字元
  • 通常用於 match 任何字元,但實際上不能

例如:常見的 \n 不能被 . match:

/foo.bar/.test('foo\nbar');
// false

過去只能用一些特殊技巧來解決這個問題,例如:[\s\S][^]

/foo[^]bar/.test('foo\nbar');
// true

/foo[\s\S]bar/.test('foo\nbar');
// true

註:在 ECMAScript spec 的定義中,RegExp pattern 中的 \s 不只 match white space,也可 match line terminator。

/\s/.test(' ');  // true
/\s/.test('\f');  // true

/\s/.test('\n');  // true
/\s/.test('\r');  // true

資料來源


上一篇
JavaScript 之旅 (8):Promise.prototype.finally()
下一篇
JavaScript 之旅 (10):RegExp Named Capture Groups
系列文
JavaScript 之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言