Javascript 替代品中的正则表达式 Lookbehind
Posted
技术标签:
【中文标题】Javascript 替代品中的正则表达式 Lookbehind【英文标题】:Regex Lookbehind in Javascript Alternatives 【发布时间】:2019-01-18 11:41:09 【问题描述】:我正在尝试在 JS 中使用以下正则表达式:
(?<=@[A-Z|a-z]+,)\s|(?<=@[A-Z|a-z]+,\s[A-Z|a-z]+)\s(?=\[[A-Z|a-z]+\])
翻译成:
匹配所有以 : 开头的空格
@
后跟A-Z
或a-z
范围内的任意数量的字符
后跟逗号
或
匹配前面的所有空格:
@
后跟A-Z
或a-z
范围内的任意数量的字符
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]
。
【问题讨论】:
javascript 确实支持后视,从 ECMAScript 2018 开始。但几乎没有浏览器支持。 你想替换什么东西吗? @revo 试图替换那些空格,是的 将您的lookbehinds转换为捕获组,并在进行替换时为它们添加反向引用以使它们出现在结果中。 @revo 您能否发布一个示例作为答案 - 不完全确定如何做到这一点 【参考方案1】:我已经根据新的输入更新了我的答案
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 中使用它,因为它不允许在后视中使用量词。它们必须具有固定宽度。在此处查看右侧的错误: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, '$1$3$4'))
.as-console-wrapper max-height: 100% !important; top: 0;
【讨论】:
现场演示中[fsadsd]
后面为什么会匹配空格?
@HerrSerker 它也应该匹配@match, match [match]<<<<<<<
中第一个匹配之后的空格...应该变成@match,match[match]<<<<<<<
@alk 我不是这么理解的。不是所有的空格都应该被替换,而只是那些在给定模式之前或之前和之后的空格。在第二个模式中,空格在前缀中,而不是在要替换(删除)的匹配中
@Alk 您在原始问题中的描述具有误导性。你应该给出输入和预期输出的例子
@HerrSerker 在该示例中,我们有一个以@[a-z|A-Z]+
开头的空格,因此它也应该被替换。所以如果我们有一个像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]
【参考方案2】:
您需要做的是将后视转换为捕获组,以便将它们包含在替换字符串中(注意设置了不区分大小写的标志 (i
)):
(@[a-z]+,)([\t ]*([a-z]+)[\t ]*(?=\[[a-z]+\])|[\t ]+)
如果要删除这些空格,请替换为 $1$3
。
见live demo here
【讨论】:
怎么在你的演示中,第二个例子中 foo 后面的空格没有被删除 - 它应该变成@foo,bar[john]
更新了答案。请检查。
谢谢 - 是否很难适应这种情况来处理像这样的情况 @foo, bar foo [john]
-> @foo,barfoo[john]
所以基本上在 [john]
部分之前有任意数量的可能单词
你必须使用两个replace
调用然后str.replace(/@[a-z]+,([ \t]*[a-z]+)+(\s\[[a-z]+\])?/g, function($0) return $0.replace(/\s+/g, ''); )
【参考方案3】:
只需更新您的 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
【讨论】:
以上是关于Javascript 替代品中的正则表达式 Lookbehind的主要内容,如果未能解决你的问题,请参考以下文章
正则表达式的可变长度lookbehind-assertion替代方案
js正则匹配替代指定字符(根据img标签的src中的命名规则,用正则表达式替换成下面格式的文字)