正则表达式在Javascript替代方法中落后

时间:2019-01-18 11:41:09

标签: javascript regex regex-lookarounds lookbehind

我正在尝试在JS中使用以下正则表达式:

(?<=@[A-Z|a-z]+,)\s|(?<=@[A-Z|a-z]+,\s[A-Z|a-z]+)\s(?=\[[A-Z|a-z]+\])

转换为:

匹配所有以:开头的空格

  • @
  • 后跟A-Za-z范围内的任意数量的字符
  • 后跟逗号

OR

匹配所有前面有空格的

  • @

  • 后跟A-Za-z

  • 范围内的任意数量的字符
  • 后跟逗号
  • 后跟一个空格
  • 后跟A-Za-z范围内的任意数量的字符

AND后跟以下字符:

  • [
  • 后跟A-Za-z范围内的任意数量的字符
  • ]

但是,JS不支持后向。是否可以在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]

3 个答案:

答案 0 :(得分:2)

我已经根据新输入内容更新了答案

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; }

答案 1 :(得分:1)

您需要执行的操作是将lookbehinds转换为捕获组,以便将其包括在替换字符串中(请注意,已设置了不区分大小写的标志(i):

(@[a-z]+,)([\t ]*([a-z]+)[\t ]*(?=\[[a-z]+\])|[\t ]+)

如果要删除这些空格,请替换为$1$3

请参见live demo here

答案 2 :(得分:0)

只需更新您的Node.js版本。向后断言是ECMAScript 2018的一部分,已经在Chromium和Node.js中实现。根据{{​​3}},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://kangax.github.io/compat-table/es2016plus/