做者:wanago翻译:疯狂的技术宅javascript
原文:https://wanago.io/2018/05/14/...html
未经容许严禁转载前端
前文(点击直达):java
到如今为止,咱们已经介绍了许多正则表达式的功能。可是还有更多。此次咱们将会学习一些更高级的概念,例如搜索和覆盖 JavaScript 中 RegExp 对象的更多功能。咱们还将学习如何使用 ES6 带来的一些功能。开始吧!git
这是一种执行搜索字符串中的匹配项的方法(相似于 test 方法),可是它返回的结果是数组(或 null)。其结果还有其余一些属性,例如 index 和 input程序员
const string = 'fileName.png, fileName2.png, fileName3.png'; const regexp = /fileName[0-9]?.png/g; regexp.exec(string); [ 0: "fileName.png", index: 0, input: "fileName.png, fileName2.png, fileName3.png" ]
index 是匹配项的位置,input 是提供的字符串。请注意,我在这里用的是 global 标志,在课程的第一部分中已提到过。因此咱们能够经过屡次调用 exec 在字符串中寻找多个匹配项。它将 RegExp 对象的 lastIndex 属性设置为一个数字,该数字指示搜索中止的位置。es6
let resultArray; while((resultArray = regexp.exec(string)) !== null) { console.log(resultArray[0], regexp.lastIndex); } // fileName.png 12 // fileName2.png 27 // fileName3.png 42
使用正则表达式,不只能够检查字符串是否匹配,还能够在忽略没必要要字符的同时提取某些信息。可使用带有圆括号的分组。github
function getDateFromString(dateString) { const regexp = /([0-9]{2})-([0-9]{2})-([0-9]{4})/; const result = regexp.exec(dateString); if(result) { return { day: result[1], month: result[2], year: result[3] } } } getDateFromString('14-05-2018');
{ day: '14', month: '05', year: '2018' }
在这种状况下,咱们提取了三组字符,而忽略了破折号。只需注意 result [0]
将是匹配的完整字符串。面试
已经有一个处于第4阶段的命名组提案,而且在上述用例中被证实是有帮助的。 Axel Rauschmayer 在 2ality 博客上的文章中对此进行了很好的描述。正则表达式
你能够嵌套分组:
function getYearFromString(dateString) { const regexp = /[0-9]{2}-[0-9]{2}-([0-9]{2}([0-9]{2}))/; const result = regexp.exec(dateString); if(result) { return { year: result[1], yearShort: result[2] } } } getYearFromString('14-05-2018');
{ year: '2018', yearShort: '18' }
在模式的 ([0-9]{2}([0-9]{2}))
部分中,咱们将一组嵌套在另外一组中。多亏了这一点,咱们获得了表示年份的短字符串。
还有另外一个有用的功能,即 OR 语句。咱们能够用 |
字符实现:
function doYearsMatch(firstDateString, secondDateString) { const execResult = /[0-9]{2}-[0-9]{2}-([0-9]{4})/.exec(firstDateString); if(execResult) { const year = execResult[1]; const yearShort = year.substr(2,4); return RegExp(`[0-9]{2}-[0-9]{2}-(${year}|${yearShort})`).test(secondDateString); } } doYearsMatch('14-05-2018', '12-02-2018'); // true doYearsMatch('14-05-2018', '24-04-18'); // true
按照咱们的模式,(${year}|${yearShort})
将会匹配年份,即便第二个年份以简短形式提供。
与组一块儿工做时,还有一个特别有用的地方:(. *)
function getResolution(resolutionString) { const execResult = /(.*) ?x ?(.*)/.exec(resolutionString); if(execResult) { return { width: execResult[1], height: execResult[2] } } }
getResolution('1024x768'); { width: '1024', height: '768' }
多亏用了 ?
运算符,若是还有其余空格,它也将起做用:
getResolution('1920 x 1080'); { width: '1920', height: '1080' }
如你所见,RegExp 对象有一个名为 lastIndex 的属性。当进行全局搜索(使用适当的标志)时,能够在正确的位置继续进行模式匹配。使用 ES6 中引入的 粘性标志 y
,咱们能够强制从某个索引开始搜索。
function getDateFromString(dateString) { const regexp = /([0-9]{2})-([0-9]{2})-([0-9]{4})/y; regexp.lastIndex = 14; const result = regexp.exec(dateString); if(result){ return { day: result[1], month: result[2], year: result[3] } } } getDateFromString('Current date: 14-05-2018');
请记住,对字符串执行检查(例如使用 exec)会更改 lastIndex 属性,因此若是你但愿它在屡次粘性搜索之间保持不变,请不要忘记对其进行设置。若是模式匹配失败,则将 lastIndex 设置为0。
注意:你能够检查 RegExp 对象是否启用了标志。
const regexp = /([0-9]{2})-([0-9]{2})-([0-9]{4})/y; regexp.lastIndex = 14; console.log(regexp.sticky); // true
其余标志也是如此:更多相关的标志,请访问 MDN Web 文档。
ES6 也带来了对 Unicode 的更好支持。添加 Unicode 标志 u
能够启用与 Unicode 相关的其余功能。多亏了它,你能够在模式中使用 \u{x}
,其中 x 是所需字符的编码。
/\u{24}/u.test('$'); // true
以上代码若是没有 u
标志将会没法工做。重要的是要知道它的影响不只限于此。若是不带标志,也能够处理一些的更特殊的 Unicode 字符:
/😹/.test('😹'); // true
但这会在更复杂的状况下使咱们失败:
/a.b/.test('a😹b'); // false /a.b/u.test('a😹b'); // true /😹{2}/.test('😹😹'); // false /😹{2}/u.test('😹😹'); // true /[a😹b]/.test('😹'); // false /[😹🐶]/u.test('😹'); // true /^[^x]$/.test('😹'); // false /[^x]/.test('😹'); // true /^[^x]$/u.test('😹'); // true /^[ab😹]$/.test('😹'); // false /[ab😹]/.test('😹'); // true /^[ab😹]$/u.test('😹'); // true
咱们能够很容易地得出一个结论,那就是在模式中包含 u
标志是一种很好的作法,尤为是再可能含有除了标准 ASCII 以外的其余字符的状况。
若是将它与 忽略大小写 标志结合使用,则该模式也将同时匹配小写和大写字符。
/\u{78}/ui.test('X'); // true
有趣的是,在 HTML 中 input 和 textarea 元素的 pattern 属性中,默认状况下启用此标志。
今天,咱们了解了有关 JavaScript 中的 RegExp 对象的更多信息,以及如何经过正则表达式的一个强大功能来运用这个知识:分组。咱们还学习了两个新标记:粘性和 Unicode。下次再见!