在编译时检测不受支持的正则表达式功能
Detect unsupported regex features at compile time
似乎 safari 有一些正则表达式功能,即使在它的最新版本中也没有得到很好的支持(lookbehind)并抛出一些警告:
register.js:298 SyntaxError: Invalid regular expression: invalid group specifier
有没有办法在编译时使用 webpack 或任何其他工具自动检测、检查或转换这类正则表达式,因为这类错误往往会通过测试?
在我的例子中,这是导致错误的正则表达式
/(?<!\.|^)\.(?!\.+|$)/
它应该匹配字符串中间的一个点,但不匹配一连串的点,我正在尝试为这个正则表达式找到一个很好的等价物,但到目前为止我一无所获
const tests = [
'test.123.test',
'.test',
'test.',
'test.3..test',
];
//Expected
tests.forEach((test) => console.log(test.split(/(?<!\.|^)\.(?!\.+|$)/)));
//Actual
tests.forEach((test) => console.log(test.match(/^(([^.]*?)(?:\.)([^.]*?))*$/)));
你可以使用
.match(/^\.+[^.]*|[^.]*\.+$|(?:\.{2,}|[^.])+(?:\.+$)?/g)
见regex demo。详情:
^\.+[^.]*
- 一个或多个点,然后是点以外的零个或多个字符
|
- 或
[^.]*\.+$
- 除点以外的零个或多个字符,然后是一个或多个点,直到字符串结束
|
- 或
(?:\.{2,}|[^.])+(?:\.+$)?
- 一个或多个两个或多个点或除点以外的任何字符,然后是字符串末尾的一个或多个点的可选序列。
查看 JavaScript 演示:
const tests = [
'test.123.test',
'.test',
'test.',
'test.3..test',
'test.3..test.',
'..test.3.test..'
];
for (let test of tests) {
console.log(test.split(/(?<!\.|^)\.(?!\.+|$)/)); // Expected
console.log(test.match(/^\.+[^.]*|[^.]*\.+$|(?:\.{2,}|[^.])+(?:\.+$)?/g)); // Actual
}
对于我的问题的主要部分,我发现了一个 eslint plugin 能够检测 ECMA 功能(包括正则表达式后视),因此通过启用已知会导致问题的功能,因为它们无法被转译, 会自动报错
{
"plugins": ["es"],
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
"es/no-async-iteration": "error",
"es/no-malformed-template-literals": "error",
"es/no-regexp-lookbehind-assertions": "error",
"es/no-regexp-named-capture-groups": "error",
"es/no-regexp-s-flag": "error",
"es/no-regexp-unicode-property-escapes": "error"
}
}
似乎 safari 有一些正则表达式功能,即使在它的最新版本中也没有得到很好的支持(lookbehind)并抛出一些警告:
register.js:298 SyntaxError: Invalid regular expression: invalid group specifier
有没有办法在编译时使用 webpack 或任何其他工具自动检测、检查或转换这类正则表达式,因为这类错误往往会通过测试?
在我的例子中,这是导致错误的正则表达式
/(?<!\.|^)\.(?!\.+|$)/
它应该匹配字符串中间的一个点,但不匹配一连串的点,我正在尝试为这个正则表达式找到一个很好的等价物,但到目前为止我一无所获
const tests = [
'test.123.test',
'.test',
'test.',
'test.3..test',
];
//Expected
tests.forEach((test) => console.log(test.split(/(?<!\.|^)\.(?!\.+|$)/)));
//Actual
tests.forEach((test) => console.log(test.match(/^(([^.]*?)(?:\.)([^.]*?))*$/)));
你可以使用
.match(/^\.+[^.]*|[^.]*\.+$|(?:\.{2,}|[^.])+(?:\.+$)?/g)
见regex demo。详情:
^\.+[^.]*
- 一个或多个点,然后是点以外的零个或多个字符|
- 或[^.]*\.+$
- 除点以外的零个或多个字符,然后是一个或多个点,直到字符串结束|
- 或(?:\.{2,}|[^.])+(?:\.+$)?
- 一个或多个两个或多个点或除点以外的任何字符,然后是字符串末尾的一个或多个点的可选序列。
查看 JavaScript 演示:
const tests = [
'test.123.test',
'.test',
'test.',
'test.3..test',
'test.3..test.',
'..test.3.test..'
];
for (let test of tests) {
console.log(test.split(/(?<!\.|^)\.(?!\.+|$)/)); // Expected
console.log(test.match(/^\.+[^.]*|[^.]*\.+$|(?:\.{2,}|[^.])+(?:\.+$)?/g)); // Actual
}
对于我的问题的主要部分,我发现了一个 eslint plugin 能够检测 ECMA 功能(包括正则表达式后视),因此通过启用已知会导致问题的功能,因为它们无法被转译, 会自动报错
{
"plugins": ["es"],
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
"es/no-async-iteration": "error",
"es/no-malformed-template-literals": "error",
"es/no-regexp-lookbehind-assertions": "error",
"es/no-regexp-named-capture-groups": "error",
"es/no-regexp-s-flag": "error",
"es/no-regexp-unicode-property-escapes": "error"
}
}