- 原文地址:Upcoming Regular Expression Features
- 原文作者:Jakob Gruber、Yang Guo
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:sunui
- 校對者:atuooo、Tina92
ES2015 給 JavaScript 語言引入了許多新特性,其中包括正規表示式語法的一些重大改進,新增了 Unicode 編碼 (/u
) 和粘滯位 (/y
)兩個修飾符。而在那之後,發展也並未停止。經過與 TC39(ECMAScript 標準委員會)的其他成員的緊密合作,V8 團隊提議並共同設計了讓正規表示式更強大的幾個新特性。
這些新特性目前已經計劃包含在 JavaScript 標準中。雖然提案還沒有完全通過,但是它們已經進入 TC39 流程的候選階段了。我們已經以試驗功能(見下文)在瀏覽器實現了這些特性,以便在最終定稿之前提供及時的設計和實現反饋給各自的提案作者。
本文給您預覽一下這個令人興奮的未來。如果您願意跟著體驗這些即將到來的示例,可以在 chrome://flags/#enable-javascript-harmony
頁面中開啟實驗性 JavaScript 功能。
命名捕獲
正規表示式可以包含所謂的捕獲(或捕獲組),它可以捕獲一部分匹配的文字。到目前為止,開發者只能通過索引來引用這些捕獲,這取決於其在正則匹配中的位置。
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'複製程式碼
但正規表示式已經因難於讀、寫和維護而臭名昭著,並且數字引用會使事情進一步複雜化。例如,在一個更長的表示式中判斷一個獨特捕獲的索引是很困難的事:
/(?:(.)(.(?<=[^(])(.)))/ // 最後一個捕獲組的索引是?複製程式碼
更糟糕的是,更改一個表示式可能會潛在地轉變所有已存在的捕獲的索引:
/(a)(b)(c)\3\2\1/ // 一些簡單的有序的反向引用。
/(.)(a)(b)(c)\4\3\2/ // 所有都需要更新。複製程式碼
命名捕獲是一個即將到來的特性,它允許開發者給捕獲組分配名稱來幫助儘可能地解決這些問題。語法類似於 Perl、Java、.Net 和 Ruby:
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.replace
:
// 命名反向引用。
/(?<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'複製程式碼
關於這個新特性的全部詳情可以在規範提案中檢視。
dotAll 修飾符
預設情況下,元字元 .
在正規表示式中匹配除了換行符以外的任何字元:
/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 Bynens、Dan Ehrenberg、Claude Pache、Brian Terlson、Thomas Wood、Gorkem Yakin、和正則大師 Erik Corry;還有為語言規範作出努力的每一個人以及 V8 團隊對這些特性的實施。
希望您能像我們一樣為這些新的正規表示式特性而感到興奮!
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、React、前端、後端、產品、設計 等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃。