【问题标题】:Finding regex that matches two children substrings within given string查找匹配给定字符串中的两个子子字符串的正则表达式
【发布时间】:2019-07-10 21:27:38
【问题描述】:

我正在尝试创建一个正则表达式,它将显示给定字符串中的两个子字符串,并且返回的值应该是一个包含两个元素的数组,即两个匹配的字符串。我知道我的问题与回文密切相关,回文不能作为正则表达式实现,但我希望正则表达式能够足够接近,因为我期望阅读的结构是有限的。

具体来说,我只关心匹配第一个示例中的两个顶级子级,其中任何数量的嵌套括号都无关紧要,无论是 1 还是 99999。

请注意,空格只是为了便于阅读,输入字符串不会有空格。这个结构很简单:

{ }{ }

并且应该被接受为两个字符串:

{ } and { }

包含在其中,可以有任意数量的大括号分组:

{ {} {} {} {} {} {} }{ {} }

并且应该被接受为两个字符串:

{ {} {} {} {} {} {} } and { {} }

包含在这些内部大括号分组中的任何一个都可以是无限递归分组,例如:

{{{{ }{{ }}{ }}}}{{ }{ }{ }}

并且应该被接受为两个字符串:

{{{{ }{{ }}{ }}}} and {{ }{ }{ }}

我自己已经想了很长时间了,但无法找到合适的解决方案,并且我发现网上没有任何工具可以直观地查看这两个子字符串,它总是只匹配整个字符串。我还使用了一些正则表达式创建器,例如“http://regex.inginf.units.it/”,并为其提供了最大数量的字符串和所有可能的边缘情况等,但只有 40% 的准确度。我希望在这个主题上比我更聪明的人可以提出一个正则表达式来拟合底部 7 个示例的答案以及根据上述规则构建的任何其他可能的字符串。

我制作了一个简单的 html 来测试我的字符串(只需编辑脚本标签中的“reg”变量以更改您的正则表达式并通过刷新页面查看结果:

var reg = /({({.*})*})/g;
var str1 = "{}{}";
var str2 = "{{}{}}{{}}";
var str3 = "{{{{{}{}{}{}}{{}}}}{}}{}";
var str4 = "{{{{{{{{{{{{{{{{{}}{{}}}}}{{}}}}}{{}}}}}{{}}}}}{{}}}}}{{}}";
var str5 = "{{}{{{{{{}{}}}}{{{{}{}}}{}}}}{}{{{}{{}}}}}{{{{{}}{{{{}{}}}}}}{{{{}}{{{{}{}}}}}}}";
var str6 = "{{}{}}{{}{{{}{}}}}";
var str7 = "{{}{}}{{{{{}}{{}}}}{{{}{}}}}";
var s1 = document.getElementById("d1").innerHTML = str1.match(reg);
var s2 = document.getElementById("d2").innerHTML = str2.match(reg);
var s3 = document.getElementById("d3").innerHTML = str3.match(reg);
var s4 = document.getElementById("d4").innerHTML = str4.match(reg);
var s5 = document.getElementById("d5").innerHTML = str5.match(reg);
var s6 = document.getElementById("d6").innerHTML = str6.match(reg);
var s7 = document.getElementById("d7").innerHTML = str7.match(reg);
<p id="d1"></p>
<p id="ans1">{},{}</p>
<p id="d2"></p>
<p id="ans2">{{}{}},{{}}</p>
<p id="d3"></p>
<p id="ans3">{{{{{}{}{}{}}{{}}}}{}},{}</p>
<p id="d4"></p>
<p id="ans4">{{{{{{{{{{{{{{{{{}}{{}}}}}{{}}}}}{{}}}}}{{}}}}}{{}}}}},{{}}</p>
<p id="d5"></p>
<p id="ans5">{{}{{{{{{}{}}}}{{{{}{}}}{}}}}{}{{{}{{}}}}},{{{{{}}{{{{}{}}}}}}{{{{}}{{{{}{}}}}}}}</p>
<p id="d6"></p>
<p id="ans6">{{}{}},{{}{{{}{}}}}</p>
<p id="d7"></p>
<p id="ans7">{{}{}},{{{{{}}{{}}}}{{{}{}}}}</p>

【问题讨论】:

  • 无法使用 JS 的原生正则表达式。虽然可能存在工具,但您可能会发现使用非正则表达式解决方案更容易。
  • 你试图做的不是正则表达式的意思。你需要的是一个解析器
  • 它不重复的原因是因为我只关心匹配两个顶级括号,没有其他数量的嵌套会以任何方式改变匹配。这就是为什么我的示例正则表达式包含“ .* ”,因为初始括号内的内容没有意义。
  • 但这仍然需要正则表达式引擎记住它当前所处的嵌套级别,而正则表达式无法做到。

标签: javascript regex regular-language


【解决方案1】:

Regex 不适合这个任务(至少 JS 风格不适合)。任何涉及可以任意嵌套的结构的东西都不适合与正则表达式匹配。这就是为什么他们说you should not use regex to parse HTML 或 JSON。请参阅此answer 了解更多信息。

您在此处的字符串很容易解析,无需使用正则表达式。通过使用正则表达式,你有点让自己的生活变得艰难。

下面是解析这个字符串的方法(假设括号总是平衡的):

  • 遍历字符串
  • 如果遇到左大括号,请在计数器变量中添加一个
  • 如果遇到右大括号,则减一
  • 计数器变量第一次达到0,即为第一个子串的结尾,其余为第二个子串。

【讨论】:

  • 我已经在使用这个确切的实现,而我想出了正则表达式(如果有的话)。
  • @Avionix 为什么你对正则表达式如此着迷?正则表达式的效率会低很多。
  • 我的印象是正则表达式能够加快这样的过程。我知道只是通过字符串是 O(n) 时间。
  • @Avionix 如果您阅读第二个链接的第二段,您会发现正则表达式要慢得多。嵌套的大括号 do 很重要,即使您认为它们不重要。您需要他们知道您当前处于哪个嵌套级别。
  • 好吧,我只是接受这个答案,因为它已经是我已经实现的。谢谢。
猜你喜欢
  • 2011-11-08
  • 2015-06-15
  • 2023-02-04
  • 2018-07-16
  • 1970-01-01
  • 1970-01-01
  • 2014-11-26
  • 1970-01-01
  • 2022-07-11
相关资源
最近更新 更多