包含字符串的第一行(仅)的正则表达式

时间:2013-08-21 10:53:56

标签: ruby regex

我有一堆电话号码,每行一个:

[Home] (202) 121-7777 
C (202) 456-1111
[mobile] 55 55 5 55555 
[Work] (404) 555-1234 
[Cell] (505) 555-1234
W 303-555-5555
M 777-555-5555
c 12346567s

我想抓住包含字母“c”大写或小写的第一个

到目前为止,我有/^.*[C].*$/i这个匹配C (202) 456-1111[Cell] (505) 555-1234c 12346567s。我如何只返回第一个?换句话说,匹配应该只是C (202) 456-1111

我盲目地question marks everywhere没有成功。

我正在使用Ruby,如果它有所作为http://www.rubular.com/r/h6ReB9IN8t

编辑:这是Hrishi指出的another question,但我无法弄清楚如何调整它以匹配整条线。

4 个答案:

答案 0 :(得分:2)

尝试match方法。这是一个例子:

list = <<EOF
[Home] (202) 121-7777 
C (202) 456-1111
[mobile] 55 55 5 55555 
[Work] (404) 555-1234 
[Cell] (505) 555-1234
W 303-555-5555
M 777-555-5555
c 12346567s
EOF

<强>更新

#match line with "c" letter in line, even that are part of word
puts list.match(/^.*C.*$/i) 

#match line with "c" letter in line, that are not a part of word
puts list.match(/^\W*C\W.*$/i) 

答案 1 :(得分:1)

按新行字符拆分字符串,select符合您要求的子字符串并抓取第一个字符串:

str = '[Home] (202) 121-7777 
C (202) 456-1111
[mobile] 55 55 5 55555 
[Work] (404) 555-1234 
[Cell] (505) 555-1234
W 303-555-5555
M 777-555-5555
c 12346567s'

p str.split(/\n/).select{|el| el =~ /^.*[C].*$/i}[0]

或使用match

p str.match(/^.*[C].*$/i)[0]

编辑:

或者,如果您想要找到以C开头的第一个块,请尝试以下操作:

p str.match(/^C.*$/)[0]

答案 2 :(得分:1)

编辑添加了另外两种处理方法。最后一个是可取的。

这将做你想要的。它将搜索你的正则表达式的匹配,然后获得第一个。请注意,如果字符串没有任何匹配项,则会产生错误。

string = "[Home] (202) 121-7777 
C (202) 456-1111
[mobile] 55 55 5 55555 
[Work] (404) 555-1234 
[Cell] (505) 555-1234
W 303-555-5555
M 777-555-5555
c 12346567s"

puts string.match(/^(.*[C].*)$/i).captures.first
puts string.match(/^(.*[C].*)$/i)
puts string[/^(.*[C].*)$/i]

Ruby Docs String#match

答案 3 :(得分:1)

我会对此有所不同。我更喜欢将正则表达式简化为非常简单的模式:

str = <<EOT
[Home] (202) 121-7777
C (202) 456-1111
[mobile] 55 55 5 55555
[Work] (404) 555-1234
[Cell] (505) 555-1234
W 303-555-5555
M 777-555-5555
c 12346567s
EOT

使用selectfind轻松完成正确的合作线:

str.split("\n").select{ |s| s[/c/i] }.first # => "C (202) 456-1111"
str.split("\n").find{ |s| s[/c/i] } # => "C (202) 456-1111"

我建议find因为它只返回第一次出现。

找到所需的字符串后,使用scan获取数字:

str.split("\n").find{ |s| s[/c/i] }.scan(/\d+/) # => ["202", "456", "1111"]

然后join他们。当您将电话号码存储在数据库中时,您实际上不希望它们被格式化,您只需要数字。稍后再次输出格式时会发生格式化。

phone_number = str.split("\n").find{ |s| s[/c/i] }.scan(/\d+/).join # => "2024561111"

当您需要输出数字时,请根据区域电话号码表示将其分成正确的分组。你应该知道这个人的位置,因为你通常也得到他们的国家代码。基于此,您知道您应该拥有多少位数,以及组:

area_code, prefix, number = phone_number[0 .. 2], phone_number[3 .. 5], phone_number[6 .. 9] # => ["202", "456", "1111"]

然后输出它们以便正确显示:

"(%s) %s-%s" % [area_code, prefix, number] # => "(202) 456-1111"

就原始模式/^.*[C].*$/i而言,您对正则表达式的理解存在一些问题:

  • ^.*说“从字符串的开头开始,找到零个或多个字符”,这并不比说/[C]更有效。
  • 使用[C]创建一个不必要的字符集,这意味着“找到集合中的一个字母”C“;它没有任何用处,所以只需使用C作为/C
  • .*$人工地找到字符串的结尾,但由于你没有捕获它,所以没有任何成就,所以不要理会它。正则表达式现在是/C/
  • 由于您要匹配大写和小写,请使用/C/i/c/i。 (或者您可以使用/[cC]/,但为什么?)

相反:

您可以获得更复杂的内容,但如果您没有使用其他模式信息完成任何操作,那么您只是在浪费正则表达式引擎的CPU时间,并且会减慢代码速度。混乱的正则表达式引擎会浪费大量的CPU时间,因此要高效并了解您要求它做的事情。