Ruby 用于查找最多n个连续模式的正则表达式
假设我们的模式是大写字母的正则表达式(但我们可能有一个比搜索大写字母更复杂的模式) 要找到至少n个连续的模式(在本例中,我们正在寻找的模式只是一个大写字母),我们可以这样做: (使用Ruby) 但是,如何搜索最多n个连续模式,例如,最多一个连续大写字母:Ruby 用于查找最多n个连续模式的正则表达式,ruby,regex,Ruby,Regex,假设我们的模式是大写字母的正则表达式(但我们可能有一个比搜索大写字母更复杂的模式) 要找到至少n个连续的模式(在本例中,我们正在寻找的模式只是一个大写字母),我们可以这样做: (使用Ruby) 但是,如何搜索最多n个连续模式,例如,最多一个连续大写字母: matches = somestring.scan(/ ??? /) => [" deFgHij kLmN pQrS ", " abcdEf"] 详细策略 我读到我需要否定“至少”正则表达式,通过将其转换为DFA,否定接受状态(然后将
matches = somestring.scan(/ ??? /)
=> [" deFgHij kLmN pQrS ", " abcdEf"]
详细策略 我读到我需要否定“至少”正则表达式,通过将其转换为DFA,否定接受状态(然后将其转换回NFA,尽管我们可以),从而将其写成正则表达式。如果我们认为遇到的模式是接收“1”,而没有接收到的模式是接收“0”,那么我们可以绘制一个简单的DFA图(其中n=1,我们最多需要一个模式): 具体来说,我想知道这是如何变成正则表达式的。一般来说,我希望找到如何找到“最多”与正则表达式,因为我的正则表达式技能感到发育不良与“至少”单独
绊倒危险-精神上不是很正确的解决方案 请注意,该问题不是重复的,因为使用公认的方法会给出:
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"]
(感谢)
但我仍然想知道如何单独使用regex查找最多n个实例。(了解一下!)要查找带有正则表达式的“至多”,可以使用后缀{1,n}
(可能前面有一个负的lookback,后面有一个正的lookahead),因此您需要的是:
irb(main):006:0> somestring.scan(/[A-Z]{1,2}/)
=> ["AB", "C", "F", "H", "L", "N", "Q", "S", "XY", "Z", "E"]
或
(但是,该正则表达式在字符串的开头和结尾可能不匹配)
看来
irb(main):026:0> somestring.split(/[A-Z]{3,}/)
=> ["", " deFgHij kLmN pQrS ", " abcdEf"]
这样会更好。为什么您的尝试无效
您当前的尝试存在一些问题
X
是匹配的一部分的原因是*
贪婪并尽可能多地消耗-因此,只留下所需的两个大写字母由尾随位匹配。这可以用一个非贪婪的量词来解决[^A-Z]+(?:[A-Z][^A-Z]+)*
那么边缘案例呢?我们可以这样说:
(?:^[A-Z])?[^A-Z]+(?:[A-Z][^A-Z]+)*(?:[A-Z]$)?
更妙的是,我们不再需要捕捉了
推广解决方案
通过将每个[A-Z]
更改为[A-Z]{1,n}
,可以很容易地将此解决方案推广到“最多n个连续大写字母”的情况,从而允许最多n个
大写字母,而到目前为止只允许一个
tl;博士
要匹配最多包含N
PATTERN
s的单词,请使用正则表达式
/\b(?:\w(?:(?<!PATTERN)|(?!(?:PATTERN){N,})))+\b/
现在,重新运行至少2个大写的正则表达式返回
at_least_2_capitals = somestring.scan(/[A-Z][A-Z]+/)
=> ["ABC", "XYZ", "DC", "DC", "TT"]
=>
注意完整的单词是如何被捕获的!你确定这就是你想要的吗?当然,我这样问是因为在后面的示例中,最多1个大写正则表达式返回完整的单词,而不仅仅是捕获的大写字母
解决方案 不管怎样,这都是解决办法 首先,为了只匹配模式(而不是整个单词,与您最初的示例一致),这里有一个用于最多-
N
-PATTERN
s的正则表达式:
进一步举例说明,最多2个大写regex返回
at_least_2_capitals = somestring.scan(/[A-Z][A-Z]+/)
=> ["ABC", "XYZ", "DC", "DC", "TT"]
=>
最后,如果您想匹配最多包含一定数量连续模式的整个单词,那么这里有一种完全不同的方法:
/\b(?:\w(?:(?<![A-Z])|(?![A-Z]{1,})))+\b/
一般形式是
/\b(?:\w(?:(?<!PATTERN)|(?!(?:PATTERN){N,})))+\b/
/\b(?:\w(?)?
您可以在中看到所有这些示例。如何从Q3到Q4?已修复。我重写得很整齐,但没有找到标签!由于缺乏简洁的解释,我忽略了尝试解释epsilon(字符串末尾)计为“0”在图中,表示接受以一个大写字母结尾的内容。你看过OPs示例输入了吗?这不是他要找的。他想找到最长的子字符串,这些子字符串包含的子模式的连续匹配项不超过n
。他明确地说我认为他的示例输入/输出是嗯(与使用拆分和匹配其他内容相反)。抱歉,这不清楚!我的意思是,如何获得=>[“deFgHij kLmN pQrS”,“abcdEf mixedCa”
/(?<!PATTERN)(?!(?:PATTERN){N+1,})(?:PATTERN)+/
/(?<![A-Z])(?!(?:[A-Z]){2,})(?:[A-Z])+/
=> ["F", "H", "L", "N", "Q", "S", "E", "C", "DC", "I", "C", "I", "DC", "T", "TT"]
=>
/\b(?:\w(?:(?<![A-Z])|(?![A-Z]{1,})))+\b/
["deFgHij", "kLmN", "pQrS", "abcdEf", "mixedCaps", "mIxedCaps", "T", "t", "tt"]
/\b(?:\w(?:(?<!PATTERN)|(?!(?:PATTERN){N,})))+\b/