加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 用于查找最多n个连续模式的正则表达式

发布时间:2020-12-17 03:16:25 所属栏目:百科 来源:网络整理
导读:让我们说我们的模式是大写字母的正则表达式(但我们可能有比搜索大写更复杂的模式) 要找到至少n个连续模式(在这种情况下,我们正在寻找的模式只是一个大写字母),我们可以这样做: (使用Ruby) somestring = "ABC deFgHij kLmN pQrS XYZ abcdEf"at_least_2_capit
让我们说我们的模式是大写字母的正则表达式(但我们可能有比搜索大写更复杂的模式)

要找到至少n个连续模式(在这种情况下,我们正在寻找的模式只是一个大写字母),我们可以这样做:

(使用Ruby)

somestring = "ABC deFgHij kLmN pQrS XYZ abcdEf"

at_least_2_capitals = somestring.scan(/[A-Z][A-Z]+/)
=> ["ABC","XYZ"]
at_least_3_capitals = somestring.scan(/[A-Z]{3}[A-Z]*/)
=> ["ABC","XYZ"]

但是,如何搜索最多n个连续模式,例如,最多连续一个大写字母:

matches = somestring.scan(/ ??? /)
=> [" deFgHij kLmN pQrS "," abcdEf"]

详细的策略

我读到我需要否定“至少”正则表达式,将其转换为DFA,否定接受状态,(然后将其转换回NFA,尽管我们可以leave it as it is),以便将其写为正则表达式.如果我们将我们的模式看作接收’1’并且没有接收到接收’0’的模式,我们可以绘制一个简单的DFA图(其中n = 1,我们最多想要一个模式):

具体来说,我想知道这是如何成为一个正则表达式.一般来说,我希望找到如何用正则表达式找到“最多”,因为我的正则表达式技能感到特别“至少”单独发痒.

旅行危险 – 在精神上不是正确的解决方案

请注意,这个问题不是this post的重复,因为使用公认的方法会给出:

somestring.scan(/[A-Z]{2}[A-Z]*(.*)[A-Z]{2}[A-Z]*/)
=> [[" deFgHij kLmN pQrS X"]]

这不是DFA所展示的,不仅仅是因为它错过了第二次寻求的匹配 – 更重要的是,它包括’X’,它不应该,因为’X’后面是另一个资本,而且从DFA我们看到一个资本,其次是另一个资本,不是接受国.

你可以建议

somestring.split(/[A-Z]{2}[A-Z]*/)
=> [""," deFgHij kLmN pQrS "," abcdEf"]

(感谢Rubber Duck)

但我仍然想知道如何仅使用正则表达式找到最多n次出现. (知识!)

解决方法

为什么你的尝试不起作用

您当前的尝试存在一些问题.

> X是匹配的一部分的原因是.*是贪婪的并且尽可能地消耗 – 因此,只留下所需的两个大写字母与尾随位匹配.这可以用非贪婪的量词来修复.
>你没有得到第二场比赛的原因是双重的.首先,您需要两个尾随大写字母,而不是字符串的结尾.其次,比赛不能重叠.第一个匹配包括至少两个尾随大写字母,但第二个匹配需要在开始时再次匹配这些不可能.
>还有更多隐藏的问题:尝试输入四个连续的大写字母 – 它可以给你一个空的匹配(前提是你使用非贪婪的量词 – 贪婪的问题甚至更糟).

用当前的方法解决所有这些问题很难(我尝试过并且失败了 – 如果你想看到我的尝试,请检查这篇文章的编辑历史,直到我决定完全废弃这种方法).所以让我们试试别的!

寻找另一种解决方案

我们想要匹配的是什么?忽略边缘情况,匹配从字符串的开头开始或在字符串的结尾处结束,我们希望匹配:

(non-caps) 1 cap (non-caps) 1 cap (non-caps) ….

这是Jeffrey Friedl的unrolling-the-loop的理想选择.看起来像

[^A-Z]+(?:[A-Z][^A-Z]+)*

现在边缘情况怎么样?我们可以这样说出来:

>我们希望在比赛开始时允许一个大写字母,只要它在字符串的开头.
>我们希望在比赛结束时允许一个大写字母,只要它在字符串的末尾.

要将这些添加到我们的模式中,我们只需将大写字母与适当的锚分组,并将它们标记为可选:

(?:^[A-Z])?[^A-Z]+(?:[A-Z][^A-Z]+)*(?:[A-Z]$)?

Now it’s really working.更好的是,我们不再需要捕捉了!

推广解决方案

通过将每个[A-Z]改变为[A-Z] {1,n},从而允许最多n个大写字母到目前为止只允许一个大写字母,这个解决方案很容易推广到“最多n个连续大写字母”的情况.

See the demo for n = 2.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读