Javascript 备选方案中的正则表达式回顾
Regex Lookbehind in Javascript Alternatives
我正在尝试在 JS 中使用以下正则表达式:
(?<=@[A-Z|a-z]+,)\s|(?<=@[A-Z|a-z]+,\s[A-Z|a-z]+)\s(?=\[[A-Z|a-z]+\])
转换为:
匹配前面有 :
的所有 space
@
- 后跟
A-Z
或 a-z
范围内的任意数量的字符
- 后跟一个逗号
或
匹配所有 space 前面有:
@
后跟 A-Z
或 a-z
范围内的任意数量的字符
- 后跟一个逗号
- 后跟 space
- 后跟
A-Z
或 a-z
范围内的任意数量的字符
AND 后接:
[
- 后跟
A-Z
或 a-z
范围内的任意数量的字符
]
但是,JS 不支持lookbehind。有没有其他方法可以在 JS 或我可以使用的任何 npm 库中支持上述正则表达式?
所以如果我们有这样的句子
Hi my name is @John, Doe [Example] and I am happy to be here
应该变成
Hi my name is @John,Doe[Example] and I am happy to be here
.
另外,如果我们有类似
Hi my name is @John, Smith Doe [Example]
,那应该变成
Hi my name is @John,SmithDoe[Example]
.
我已经根据新输入更新了我的答案
console.clear();
var inputEl = document.querySelector('#input')
var outputEl = document.querySelector('#output')
function rep (e) {
var input = e.target.value;
var reg = /@([a-z]+?\s*?)+,(\s+[a-z]+)+(\s\[[a-z]+\])?/gim
matches = input.match(reg);
var output = input;
if (matches) {
replaceMap = new Map()
for (var i = 0; i < matches.length; i++) {
var m = matches[i]
.replace(/\[/, '\[')
.replace(/\]/, '\]')
replaceMap.set(m, matches[i].replace(/\s+/gm, ''))
}
for (var [s,r] of replaceMap) {
output = output.replace(new RegExp(s, 'gm'), r)
}
}
outputEl.textContent = output
}
inputEl.addEventListener('input', rep)
inputEl.dispatchEvent(new Event('input'))
textarea {
width: 100%;
min-height: 100px;
}
<h3>Input</h3>
<textarea id="input">@Lopez de la Cerda, Antonio Gabriel Hugo David [Author]. I'm the father of @Marquez, Maria</textarea>
<h3>Output (initially empty)</h3>
<p id="output"></p>
<h3>Expected result (on initial input)</h3>
<p>@LopezdelaCerda,AntonioGabrielHugoDavid[Author]. I'm the father of @Marquez,Maria</p>
旧答案内容备份(历史原因)
它至少在 Chrome 中使用此正则表达式:
/(?<=@[a-z]+,)\s+(?![a-z]+\s+\[[a-z]+\])|(?<=(@[a-z]+,\s[a-z]+))\s+(?=\[[a-z]+\])/gmi
参见:https://regex101.com/r/elTkRe/4
但是你不能在 PCRE 中使用它,因为它不允许在 lookbehinds 中有量词。它们必须具有固定宽度。在此处查看右侧的错误:https://regex101.com/r/ZC3XmX/2
不回头看和向前看的解决方案
console.clear();
var reg = /(@[A-Za-z]+,\s[A-Za-z]+)(\s+)(\[[A-Za-z]+\])|(@[A-Z|a-z]+,)(\s+)/gm
var probes = [
'@gotAMatch, <<<',
'@LongerWithMatch, <<<',
'@MatchHereAsWell, <<<',
'@Yup, <<<<',
'@noMatchInThisLine,<<<<<',
'@match, match [match]<<<<<<<',
'@ noMatchInThisLine, <<<<'
]
for (var i in probes) {
console.log(probes[i].replace(reg, ''))
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
您需要做的是将 lookbehinds 转换为捕获组,以便将它们包含在替换字符串中(注意设置了不区分大小写的标志 (i
)):
(@[a-z]+,)([\t ]*([a-z]+)[\t ]*(?=\[[a-z]+\])|[\t ]+)
如果要删除这些空格,请替换为
。
只需更新您的 Node.js 版本。 Lookbehind 断言是 ECMAScript 2018 的一部分,并且已经在 Chromium 和 Node.js 中实现。根据 http://kangax.github.io/compat-table/es2016plus/,Chromium 70 和 Node.js 8.10 具有此功能。
我刚刚在浏览器和 Node.js (v8.11) 中对其进行了测试,可以确认:
node -e "console.log('nothing@xyz, bla'.match(/(?<=@[A-Za-z]+,)\s+/))"
如果你不能更新,你必须使用其他策略,如捕获和替换,这应该不是一个大问题,正面回顾(负面更难):
const hit = 'nothing@xyz, bla'.match(/(@[A-Za-z]+,)\s+/)
hit[0].replace(hit[1])
如果没有别的办法,看看这个试图实现 Lookbehind 的项目(我还没有测试过):http://blog.stevenlevithan.com/archives/javascript-regex-lookbehind
我正在尝试在 JS 中使用以下正则表达式:
(?<=@[A-Z|a-z]+,)\s|(?<=@[A-Z|a-z]+,\s[A-Z|a-z]+)\s(?=\[[A-Z|a-z]+\])
转换为:
匹配前面有 :
的所有 space@
- 后跟
A-Z
或a-z
范围内的任意数量的字符
- 后跟一个逗号
或
匹配所有 space 前面有:
@
后跟
A-Z
或a-z
范围内的任意数量的字符
- 后跟一个逗号
- 后跟 space
- 后跟
A-Z
或a-z
范围内的任意数量的字符
AND 后接:
[
- 后跟
A-Z
或a-z
范围内的任意数量的字符
]
但是,JS 不支持lookbehind。有没有其他方法可以在 JS 或我可以使用的任何 npm 库中支持上述正则表达式?
所以如果我们有这样的句子
Hi my name is @John, Doe [Example] and I am happy to be here
应该变成
Hi my name is @John,Doe[Example] and I am happy to be here
.
另外,如果我们有类似
Hi my name is @John, Smith Doe [Example]
,那应该变成
Hi my name is @John,SmithDoe[Example]
.
我已经根据新输入更新了我的答案
console.clear();
var inputEl = document.querySelector('#input')
var outputEl = document.querySelector('#output')
function rep (e) {
var input = e.target.value;
var reg = /@([a-z]+?\s*?)+,(\s+[a-z]+)+(\s\[[a-z]+\])?/gim
matches = input.match(reg);
var output = input;
if (matches) {
replaceMap = new Map()
for (var i = 0; i < matches.length; i++) {
var m = matches[i]
.replace(/\[/, '\[')
.replace(/\]/, '\]')
replaceMap.set(m, matches[i].replace(/\s+/gm, ''))
}
for (var [s,r] of replaceMap) {
output = output.replace(new RegExp(s, 'gm'), r)
}
}
outputEl.textContent = output
}
inputEl.addEventListener('input', rep)
inputEl.dispatchEvent(new Event('input'))
textarea {
width: 100%;
min-height: 100px;
}
<h3>Input</h3>
<textarea id="input">@Lopez de la Cerda, Antonio Gabriel Hugo David [Author]. I'm the father of @Marquez, Maria</textarea>
<h3>Output (initially empty)</h3>
<p id="output"></p>
<h3>Expected result (on initial input)</h3>
<p>@LopezdelaCerda,AntonioGabrielHugoDavid[Author]. I'm the father of @Marquez,Maria</p>
旧答案内容备份(历史原因)
它至少在 Chrome 中使用此正则表达式:
/(?<=@[a-z]+,)\s+(?![a-z]+\s+\[[a-z]+\])|(?<=(@[a-z]+,\s[a-z]+))\s+(?=\[[a-z]+\])/gmi
参见:https://regex101.com/r/elTkRe/4
但是你不能在 PCRE 中使用它,因为它不允许在 lookbehinds 中有量词。它们必须具有固定宽度。在此处查看右侧的错误:https://regex101.com/r/ZC3XmX/2
不回头看和向前看的解决方案
console.clear();
var reg = /(@[A-Za-z]+,\s[A-Za-z]+)(\s+)(\[[A-Za-z]+\])|(@[A-Z|a-z]+,)(\s+)/gm
var probes = [
'@gotAMatch, <<<',
'@LongerWithMatch, <<<',
'@MatchHereAsWell, <<<',
'@Yup, <<<<',
'@noMatchInThisLine,<<<<<',
'@match, match [match]<<<<<<<',
'@ noMatchInThisLine, <<<<'
]
for (var i in probes) {
console.log(probes[i].replace(reg, ''))
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
您需要做的是将 lookbehinds 转换为捕获组,以便将它们包含在替换字符串中(注意设置了不区分大小写的标志 (i
)):
(@[a-z]+,)([\t ]*([a-z]+)[\t ]*(?=\[[a-z]+\])|[\t ]+)
如果要删除这些空格,请替换为 。
只需更新您的 Node.js 版本。 Lookbehind 断言是 ECMAScript 2018 的一部分,并且已经在 Chromium 和 Node.js 中实现。根据 http://kangax.github.io/compat-table/es2016plus/,Chromium 70 和 Node.js 8.10 具有此功能。
我刚刚在浏览器和 Node.js (v8.11) 中对其进行了测试,可以确认:
node -e "console.log('nothing@xyz, bla'.match(/(?<=@[A-Za-z]+,)\s+/))"
如果你不能更新,你必须使用其他策略,如捕获和替换,这应该不是一个大问题,正面回顾(负面更难):
const hit = 'nothing@xyz, bla'.match(/(@[A-Za-z]+,)\s+/)
hit[0].replace(hit[1])
如果没有别的办法,看看这个试图实现 Lookbehind 的项目(我还没有测试过):http://blog.stevenlevithan.com/archives/javascript-regex-lookbehind