我会有所不同。我更喜欢将正则表达式简化为非常简单的模式:
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
使用select
or可以轻松找到要使用的正确线路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”中找到一个字母;它没有任何用处,所以只需使用C
as /C
。
.*$
人为地也找到了字符串的结尾,但是由于您没有捕获它,所以没有完成任何事情,所以不要打扰它。正则表达式现在是/C/
.
- 由于要匹配大小写,请使用
/C/i
or /c/i
。(或者你可以使用/[cC]/
,但为什么?)
反而:
您可能会变得更加复杂,但是如果您没有使用额外的模式信息完成任何事情,那么您只是在浪费正则表达式引擎的 CPU 时间,并减慢您的代码。一个混乱的正则表达式引擎会浪费大量的 CPU 时间,所以要高效并知道你要求它做什么。