我使用的是Ruby 2.4。我想匹配一个可选的" a"或" b"字符,后跟一个任意数量的空格,然后是一个或多个数字,但我的正则表达式无法匹配其中任何一个:
2.4.0 :017 > MY_TOKENS = ["a", "b"]
=> ["a", "b"]
2.4.0 :018 > str = "40"
=> "40"
2.4.0 :019 > str =~ Regexp.new("^[#{Regexp.union(MY_TOKENS)}]?[[:space:]]*\d+[^a-z^0-9]*$")
=> nil
2.4.0 :020 > str =~ Regexp.new("^#{Regexp.union(MY_TOKENS)}?[[:space:]]*\d+[^a-z^0-9]*$")
=> nil
2.4.0 :021 > str =~ Regexp.new("^#{Regexp.union(MY_TOKENS)}?[[:space:]]*\d+$")
=> nil
我对我做错了什么感到难过。
答案 0 :(得分:3)
如果它们是单个字符,只需在字符类中使用MY_TOKENS.join
:
MY_TOKENS = ["a", "b"]
str = "40"
first_regex = /^[#{MY_TOKENS.join}]?[[:space:]]*\d+[^a-z0-9]*$/
# /^[ab]?[[:space:]]*\d+[^a-z0-9]*$/
puts str =~ first_regex
# 0
你也可以集成Regexp.union,它可能会导致some unexpected bugs,因为外部正则表达式的标志不适用于内部正则表达式:
second_regex = /^#{Regexp.union(MY_TOKENS)}?[[:space:]]*\d+[^a-z0-9]*$/
# /^(?-mix:a|b)?[[:space:]]*\d+[^a-z0-9]*$/
puts str =~ second_regex
# 0
上面的正则表达式看起来很像你所做的,但使用//
而不是Regexp.new
可以防止你不得不逃避反斜杠。
您可以使用Regexp#source
来避免此行为:
third_regex = /^(?:#{Regexp.union(MY_TOKENS).source})?[[:space:]]*\d+[^a-z0-9]*$/
# /^(?:a|b)?[[:space:]]*\d+[^a-z0-9]*$/
puts str =~ third_regex
# 0
或简单地构建你的正则表达式联合:
fourth_regex = /^(?:#{MY_TOKENS.join('|')})?[[:space:]]*\d+[^a-z0-9]*$/
# /^(?:a|b)?[[:space:]]*\d+[^a-z0-9]*$/
puts str =~ fourth_regex
# 0
如果MY_TOKENS
包含单词而非单词,则最后3个示例应该可以正常工作。
first_regex
,third_regex
和fourth_regex
应该可以正常使用/i
标记。
举个例子:
first_regex = /^[#{MY_TOKENS.join}]?[[:space:]]*\d+[^a-z0-9]*$/i
"A 40" =~ first_regex
# 0
答案 1 :(得分:1)
我相信您希望匹配一个字符串,该字符串可能包含您在MY_TOKENS
中定义的任何替代字符,然后是0 +空格,然后是一个或多个数字,直到字符串的结尾。
然后你需要使用
Regexp.new("\\A#{Regexp.union(MY_TOKENS)}?[[:space:]]*\\d+\\z").match?(s)
或
/\A#{Regexp.union(MY_TOKENS)}?[[:space:]]*\d+\z/.match?(s)
使用Regexp.new
时,您应该记住双重转义反斜杠以定义文字反斜杠(例如“\ d”是数字匹配模式)。在正则表达式文字表示法中,您可以使用单个反斜杠(/\d/
)。
不要忘记将字符串的开头与\A
匹配,将字符串的结尾与\z
个锚点匹配。
请注意[...]
创建一个匹配其中定义的任何字符的字符类:[ab]
匹配a
或b
,[program]
将匹配一个字符,p
,r
,o
,g
,r
,a
或m
。如果MY_TOKENS
中有多字符序列,则需要从模式中删除[...]
。
要使正则表达式不区分大小写,请将不区分大小写的修饰符传递给模式,并确保使用.source
创建的正则表达式的Regex.union
属性来删除标记(谢谢,Eric) :
Regexp.new("(?i)\\A#{Regexp.union(MY_TOKENS).source}?[[:space:]]*\\d+\\z")
或
/\A#{Regexp.union(MY_TOKENS).source}?[[:space:]]*\d+\z/i
创建的正则表达式为/(?i-mx:\Aa|b?[[:space:]]*\d+\z)/
,其中(?i-mx)
表示不区分大小写的模式已启用且多行(点匹配换行符和详细模式已关闭)。