我在文档中看到我能够做到:
/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0
puts dollars #=> prints 3
我想知道这是否可行:
string = "\$(\?<dlr>\d+)\.(\?<cts>\d+)"
/#{Regexp.escape(string)}/ =~ "$3.67"
我明白了:
`<main>': undefined local variable or method `dlr' for main:Object (NameError)
答案 0 :(得分:1)
你的方法有一些错误。首先,让我们看一下你的字符串:
string = "\$(\?<dlr>\d+)\.(\?<cts>\d+)"
您使用"\$"
转义美元符号,但这与撰写"$"
相同,请考虑:
"\$" == "$"
#=> true
要实际结束字符串“反斜杠后跟美元”,您需要写"\\$"
。同样的事情适用于十进制字符类,您必须编写"\\d"
以最终得到正确的字符串。
另一方面,问号实际上是正则表达式语法的一部分,所以你根本不想逃避它们。我建议对原始字符串使用单引号,因为这样可以使输入更容易:
string = '\$(?<dlr>\d+)\.(?<cts>\d+)'
#=> "\\$(?<dlr>\\d+)\\.(?<cts>\\d+)"
下一期是Regexp.escape
。看看它用上面的字符串产生的正则表达式:
string = '\$(?<dlr>\d+)\.(?<cts>\d+)'
Regexp.escape(string)
#=> "\\\\\\$\\(\\?<dlr>\\\\d\\+\\)\\\\\\.\\(\\?<cts>\\\\d\\+\\)"
这是一个太多逃避的水平。当您想要匹配字符串中包含的文字字符时,可以使用Regexp.escape
。例如,上面的转义正则表达式将匹配源字符串本身:
/#{Regexp.escape(string)}/ =~ string
#=> 0 # matches at offset 0
相反,您可以使用Regexp.new
将源视为实际的正则表达式。
最后一个问题是如何访问匹配结果。显然,你得到的是NoMethodError
。您可能认为匹配结果存储在名为dlr
和cts
的局部变量中,但事实并非如此。您有两种方法可以访问匹配数据:
Regexp.match
,它将返回MatchData
个对象regexp =~ string
,然后使用全局变量$~
我更喜欢前者,因为它更容易阅读。完整的代码将如下所示:
string = '\$(?<dlr>\d+)\.(?<cts>\d+)'
regexp = Regexp.new(string)
result = regexp.match("$3.67")
#=> #<MatchData "$3.67" dlr:"3" cts:"67">
result[:dlr]
#=> "3"
result[:cts]
#=> "67"