【问题标题】:Regex loops continuously without terminating to find a match正则表达式连续循环而不终止寻找匹配
【发布时间】:2019-05-19 07:43:03
【问题描述】:

我需要找到匹配的位置,我已经尝试过

function myFunction() {
  var myvar_thru_textbox="u?"

  var ptrn = new RegExp(myvar_thru_textbox, "gim");

  var match;

  while ((match = ptrn.exec("color colour")) != null) {
    console.log(JSON.stringify(match));   
  }

}

此代码使用字符串“”产生无限输出

当模式变为“ou?”时它产生正确的输出,为什么?如果前面有单个字符,字符会变为无穷大?

我希望只在“u?”时产生“”或“u”。使用正则表达式。

【问题讨论】:

  • /u?/ 将匹配空字符串和“u”。那个空字符串是个问题,因为在任何给定的字符串中都有无限的实例。
  • 先检查是否为空,如果是则拒绝。
  • 但这将永远持续下去,这也会阻止底层的非空匹配文本
  • 在你的例子中,你为什么不能只使用"u" 而不是"u?"?我认为没有充分的理由搜索空字符串片段。
  • 啊,好吧,我明白了。您实际上是在询问如何清理用户提供的正则表达式。这是停机问题的变体,没有解决方案。通常,一个足够好的解决方法是在经过多次迭代或经过一段时间后取消。

标签: javascript regex


【解决方案1】:

根据documentation,

JavaScript RegExp 对象在设置了全局或粘性标志时是有状态的(例如 /foo/g 或 /foo/y)。他们存储上一场比赛的lastIndex。

...

如果匹配成功,则exec()方法返回一个数组并更新正则表达式对象的lastIndex属性。

现在想象一下第一次迭代会发生什么。正则表达式在索引 0 处找到零宽度匹配,因此将 lastIndex 设置为 0。然后在第二次迭代中,它从 0 开始搜索,在那里找到另一个零宽度匹配,因此将 lastIndex 设置为 0再次。并且循环继续。

因此,您应该在那里放置一个 if 语句来检查匹配是否为零宽度。如果是,增加最后一个索引,这样它就不会再给你同样的匹配。

function myFunction() {
  var ptrn = new RegExp("u?", "gim");

  var match;
  var i = 0;

  while ((match = ptrn.exec("color colour")) != null) {
    console.log(JSON.stringify(match));
    if (match.index == ptrn.lastIndex) {
      ptrn.lastIndex++;
    }

  }

}
myFunction()

【讨论】:

    【解决方案2】:

    ? 表示“零或一”。 u? 表示“匹配u 的单个实例或空的单个实例。”因此,u? 无限次匹配您的字符串也就不足为奇了。我想我不会预料到这一点,但这并不令人担忧。

    当您将正则表达式更改为 ou? 时,这意味着“需要一个 o,可选地后跟一个 u”。它不的意思是“找到零个或一个ou 组合”。你的字符串中有两个os,这意味着它会匹配两次。

    【讨论】:

    • 我知道,但我正在寻找一种解决方案来找到匹配的文本,而不绕过底层的非空文本。预期的输出只能是“”和“u”。
    • 您的问题是“为什么 ? 如果前面有一个字符,字符会变成无穷大?”我已经回答了这个问题。你的帖子没有告诉我们你希望达到什么结果,而且我不读心术,所以我不知道如何构建你暗中想要的东西。
    • 你可以参考上面的Sweepers回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-27
    • 2022-11-22
    • 2011-08-11
    • 1970-01-01
    相关资源
    最近更新 更多