2

在下面的示例中,我无法弄清楚我在做什么不同。我有两个字符串,在我看来是相似的 - 纯字符串。对于每个字符串,我都有一个正则表达式,但第一个正则表达式 ./\*Hi (.*) \*,/给了我一个结果,其中正则表达式匹配出现在 2 个数组中:[["result"]]. 我需要我的结果只显示在 1 个数组中:["result"]. 在下面的 2 个示例中,我做了什么不同的事情?

✗ irb
2.0.0p247 :001 > name_line_1 = "*Hi Peter Parker *,"
 => "*Hi Peter Parker *," 
2.0.0p247 :002 > name_line_1.scan(/\*Hi (.*) \*,/)
 => [["Peter Parker"]] 
2.0.0p247 :003 > name_line_2 = "Peter Parker<br />Memory Lane 60<br />0000 Gotham<br />USA<br />TEL:: 00000000000<br /><a href=\"mailto:peter5064@parker.com\">peter@parker.com</a><br />\r"
 => "Peter Parker<br />Memory Lane 60<br />0000 Gotham<br />USA<br />TEL:: 00000000000<br /><a href=\"mailto:peter5064@parker.com\">peter@parker.com</a><br />\r" 
2.0.0p247 :004 > name_line_2.scan(/^[^<]*/)
 => ["Peter Parker"]
4

3 回答 3

3

这是因为您使用括号捕获 name_line_1 中的名称。这会导致 scan 方法返回一个数组数组。如果你绝对必须返回一个一维数组,你可以像这样使用前向和后向检查:

/(?<=\*Hi ).*(?= \*,)/

或者,如果您觉得这太令人困惑,您可以随时调用.flatten结果数组;-)

于 2013-07-18T11:09:52.710 回答
3

scan返回一个匹配数组。正如其他答案所指出的那样,如果您的正则表达式具有捕获组(括号),则意味着每个匹配项都将返回一个数组,匹配项中的每个捕获组都有一个字符串。

如果它不这样做,scan就不会很有用,因为在正则表达式中使用捕获组来挑选匹配的不同部分是很常见的。

我怀疑这scan并不是适合您情况的最佳方法。scan当您想从字符串中获取所有匹配项时很有用。但是在您显示的字符串中,无论如何只有一个匹配项。如果要从字符串中的第一个匹配项中获取特定的捕获组,最简单的方法是:

 string[/regex/, 1] # extract the first capturing group, or nil if there is no match

另一种方法是做这样的事情:

 if string =~ /regex/
   # $1 will contain the first capturing group from the first match

或者:

 if match = string.match(/regex/)
   # match[1] will contain the first capturing group

如果您真的想获取字符串中的所有匹配项,并且需要使用捕获组(或者觉得它比使用前瞻和后瞻更具可读性,就是这样):

 string.scan(/regex/) do |match|
   # do something with match[0]
 end

或者:

 string.scan(/regex/).map(&:first)
于 2013-07-18T11:54:13.323 回答
0

不同之处在于,在第一个正则表达式中,您捕获了 substring ()。当正则表达式匹配时,整个匹配被捕获为$&,除此之外,您可以使用(). 它们将被捕获为$1, $2, ...

并且scan行为会有所不同,具体取决于您是否有$1, $2, ... 当您没有时,它会返回一个包含所有$&s 的数组。当你确实有$1, $2, ... 时,它会返回一个[$1, $2, ...].

为了避免$1在第一个正则表达式中,您必须避免使用捕获的子字符串:

于 2013-07-18T11:09:59.460 回答