我希望我的Ruby程序使用正则表达式来匹配具有以下模式的单词
模式有
规则:
关于字母列表,它应与
字匹配一个。 0或1 A
湾0或1 B
℃。 0或1或2 C
ABWXY(如果野性char = 1)
BAXY
CXYCB
但不是带有2个A或2个B的单词
我使用的模式如^ [ABCC] *。XY $
但它会查找超过1 A,或1 B或2 C的单词,并且还会查找以XY结尾的单词,我希望所有单词在任何地方都有XY,字母和野性字符在任何位置。< / p>
答案 0 :(得分:2)
如果它是正则表达式,可以使用以下内容:
if subject =~
/^ # start of string
(?!(?:[^A]*A){2}) # assert that there are less than two As
(?!(?:[^B]*B){2}) # and less than two Bs
(?!(?:[^C]*C){3}) # and less than three Cs
(?!(?:[ABCXY]*[^ABCXY]){3}) # and less than three non-ABCXY characters
(?=.*XY) # and that XY is contained in the string.
/x
# Successful match
else
# Match attempt failed
end
这假定字符A,B,C,X或Y都不允许作为通配符。
答案 1 :(得分:1)
你需要正确地打破你的模式。在regexp术语中,[ABCC]
表示“A,B或C中的任何一个”,其中重复的C被忽略。它是一个集合运算符,而不是像()
那样的分组运算符。
您似乎要描述的是基于参数创建正则表达式。您可以通过将字符串传递给Regexp.new
并使用结果来完成此操作。
一个例子大致是:
def match_for_options(options)
pattern = '^'
pattern << 'A' * options[:a] if (options[:a])
pattern << 'B' * options[:b] if (options[:b])
pattern << 'C' * options[:c] if (options[:c])
Regexp.new(pattern)
端
您可以使用以下内容:
if (match_for_options(:a => 1, :c => 2).match('ACC'))
# ...
end
答案 2 :(得分:1)
我认为自己在正则表达方面相当不错,我想不出办法去做你所要求的。正则表达式寻找模式,你似乎想要的是不同的模式。在您的情况下,编写一个函数可能更合适,该函数将字符串拆分为字符并计算您拥有的内容,以便您可以满足您的条件。
仅举一个问题的例子,像/ [abc] /这样的正则表达式将匹配a,b和c的每一次出现,无论这些字母出现在字符串中的次数是多少。您可以尝试/ c {1,2} /,它将匹配“c”,“cc”和“ccc”。它匹配最后一种情况,因为你在“ccc”中有一个1 c和2 c的模式。
我在开发和调试正则表达式时发现的一件事是rubular.com。尝试一些例子,我想你会看到你的反对意见。
我不知道这是否真的有任何帮助,但它可能会帮助您选择方向。
答案 3 :(得分:1)
由于您希望允许这些“元素”以任何顺序出现,您最好编写一些从头到尾遍历字符串的Ruby代码,并计算As,B和C的数量,发现它是否包含您想要的子字符串。如果As,Bs和Cs的数量在你想要的限制内,并且它包含所需的子字符串,并且它的长度(即字符数)等于所需子字符串的长度,加上As的数量,加上B的数量加上C的数量,加上最多N个字符,那么字符串就好了,否则就不好了。实际上,要小心,首先应搜索所需的子字符串,然后从原始字符串中删除,然后计算As,B和C的数量,否则您可能会无意中计算As, Bs和Cs出现在你想要的字符串中,如果有的话。
你可以用正则表达式做你想做的事,但这将是一个漫长丑陋的正则表达式。为什么?因为对于元素的每个可能的顺序,在正则表达式中需要单独的“case”。例如,正则表达式“^ ABC..XY $”将匹配任何以“ABC”开头并以“XY”结尾且中间有两个外卡字符的字符串。但只是按顺序。如果您想要所有可能订单的正则表达式,则需要在正则表达式中列出所有这些订单,例如它将开始像“^(ABC..XY | ACB..XY | BAC..XY | BCA..XY |”之类的东西,并从那里开始,大约5!= 120个不同的5个元素列表,那么对于没有A的情况你需要更多,对于没有B的情况需要更多,等等。我认为正则表达式是这里工作的错误工具。