2

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

[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

我一直盲目地到处打问号,但没有成功。

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

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

4

4 回答 4

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) 
于 2013-08-21T11:20:59.977 回答
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]
于 2013-08-21T11:21:46.223 回答
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]

红宝石文档String#match

于 2013-08-21T11:41:28.493 回答
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

使用selector可以轻松找到要使用的正确线路find

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”中找到一个字母;它没有任何用处,所以只需使用Cas /C
  • .*$人为地也找到了字符串的结尾,但是由于您没有捕获它,所以没有完成任何事情,所以不要打扰它。正则表达式现在是/C/.
  • 由于要匹配大小写,请使用/C/ior /c/i。(或者你可以使用/[cC]/,但为什么?)

反而:

您可能会变得更加复杂,但是如果您没有使用额外的模式信息完成任何事情,那么您只是在浪费正则表达式引擎的 CPU 时间,并减慢您的代码。一个混乱的正则表达式引擎会浪费大量的 CPU 时间,所以要高效并知道你要求它做什么。

于 2013-08-21T14:21:30.167 回答