要找到至少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
.
以上是内存溢出为你收集整理的ruby – 用于查找最多n个连续模式的正则表达式全部内容,希望文章能够帮你解决ruby – 用于查找最多n个连续模式的正则表达式所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)