[譯] 即將到來的正則表達式新特性

ES2015 給 JavaScript 語言引入了許多新特性,其中包括正則表達式語法的一些重大改進,新增了 Unicode 編碼 (/u) 和粘滯位 (/y)兩個修飾符。而在那以後,發展也並未中止。通過與 TC39(ECMAScript 標準委員會)的其餘成員的緊密合做,V8 團隊提議並共同設計了讓正則表達式更強大的幾個新特性。javascript

這些新特性目前已經計劃包含在 JavaScript 標準中。雖然提案尚未徹底經過,可是它們已經進入 TC39 流程的候選階段了。咱們已經以試驗功能(見下文)在瀏覽器實現了這些特性,以便在最終定稿以前提供及時的設計和實現反饋給各自的提案做者。html

本文給您預覽一下這個使人興奮的將來。若是您願意跟着體驗這些即將到來的示例,能夠在 chrome://flags/#enable-javascript-harmony 頁面中開啓實驗性 JavaScript 功能。前端

命名捕獲

正則表達式能夠包含所謂的捕獲(或捕獲組),它能夠捕獲一部分匹配的文本。到目前爲止,開發者只能經過索引來引用這些捕獲,這取決於其在正則匹配中的位置。java

const pattern =/(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-07-10');
// result[0] === '2017-07-10'
// result[1] === '2017'
// result[2] === '07'
// result[3] === '10'複製代碼

但正則表達式已經因難於讀、寫和維護而臭名昭著,而且數字引用會使事情進一步複雜化。例如,在一個更長的表達式中判斷一個獨特捕獲的索引是很困難的事:react

/(?:(.)(.(?<=[^(])(.)))/  // 最後一個捕獲組的索引是?複製代碼

更糟糕的是,更改一個表達式可能會潛在地轉變全部已存在的捕獲的索引:android

/(a)(b)(c)\3\2\1/     // 一些簡單的有序的反向引用。
/(.)(a)(b)(c)\4\3\2/  // 全部都須要更新。複製代碼

命名捕獲是一個即將到來的特性,它容許開發者給捕獲組分配名稱來幫助儘量地解決這些問題。語法相似於 Perl、Java、.Net 和 Ruby:ios

const pattern =/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-07-10');
// result.groups.year === '2017'
// result.groups.month === '07'
// result.groups.day === '10'複製代碼

命名捕獲組也能夠被命名的反向引用來引用,並傳入 String.prototype.replacegit

// 命名反向引用。
/(?<LowerCaseX>x)y\k<LowerCaseX>/.test('xyx');  //true

// 字符串替換。
const pattern =/(?<fst>a)(?<snd>b)/;
'ab'.replace(pattern,'$<snd>$<fst>');                              // 'ba'
'ab'.replace(pattern,(m, p1, p2, o, s,{fst, snd})=> fst + snd);  // 'ba'複製代碼

關於這個新特性的所有詳情能夠在規範提案中查看。github

dotAll 修飾符

默認狀況下,元字符 . 在正則表達式中匹配除了換行符之外的任何字符:web

/foo.bar/u.test('foo\nbar');   // false複製代碼

一個提案引入了 dotAll 模式,經過 /s 修飾符來開啓。在 dotAll 模式中,. 也能夠匹配換行符。

/foo.bar/su.test('foo\nbar');  // true複製代碼

關於這個新特性的所有詳情能夠在規範提案中查看。

Unicode 屬性逃逸(Unicode Property Escapes)

正則表達式語法已經包含了特定字符類的簡寫。\d 表明數字而且只能是 [0-9]\w 是單詞字符的簡寫,或者寫成 [A-Za-z0-9_]

自從 ES2015 引入了 Unicode,忽然間大量的字符能夠被認爲是數字,例如圈一:①;或者被認爲是字符的,例如中文字符:雪。

它們都不會被 \d\w 匹配。而改變這些簡寫的含義將會破壞已經存在的正則表達式模式。

因而,新的字串類被引入。注意它們只在使用 /u 修飾符的 Unicode-aware 正則表達式中可用。

/\p{Number}/u.test('①');      // true
/\p{Alphabetic}/u.test('雪');  // true複製代碼

排除型字符可使用 \P 匹配。

/\P{Number}/u.test('①');      // false
/\P{Alphabetic}/u.test('雪');  // false複製代碼

統一碼聯盟還定義了許多方式來分類碼位,例如數學符號和日語平假名字符:

/^\p{Math}+$/u.test('∛∞∉');                            // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな');  // true複製代碼

所有受支持的 Unicode 屬性類列表能夠在目前的規範提案中找到。更多示例請查看這篇內容豐富的文章

後行斷言

先行斷言從一開始就已是 JavaScript 正則表達式語法的一部分。與之相對的後行斷言也終於將被引入。大家中的一些人可能記得,這成爲 V8 的一部分已經有一段時間了。咱們甚至在底層已經用後行斷言實現了 ES2015 規定的 Unicode 修飾符。

「後行斷言」這個名字已經很好地描述了它的涵義。它提供一個方式來限制一個正則,只有後行組匹配經過以後才繼續匹配。它提供匹配和非匹配兩種選擇:

/(?<=\$)\d+/.exec('$1 is worth about ¥123');  // ['1']
/(?<!\$)\d+/.exec('$1 is worth about ¥123');  //['123']複製代碼

更多詳細信息,查看咱們以前的一篇博文,專門介紹了後行斷言。相關示例能夠查看V8 測試用例

致謝

本文的完成有幸獲得了不少相關人士的幫助,他們的辛勤工做造就了這一切:特別是語言之王Mathias BynensDan EhrenbergClaude PacheBrian TerlsonThomas Wood、Gorkem Yakin、和正則大師 Erik Corry;還有爲語言規範做出努力的每個人以及 V8 團隊對這些特性的實施。

但願您能像咱們同樣爲這些新的正則表達式特性而感到興奮!


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃

相關文章
相關標籤/搜索