2016-11-16 65 views
1

我有一个字符串,如下匹配的正则表达式的红宝石

201-Grandview-Dr_Early_TX_76802/50-Washington-St

我写一个正则表达式来匹配两个字符串。

((/^([0-9]+)-([^_]+)-([A-Za-z]{1,})$/ =~ data) == 0) 

但上述正则表达式只匹配50-Washington-St而不是第二个匹配。

那么这个正则表达式有什么问题呢?

琴弦的更新列表应符合:

201-Grandview-Dr_Early_TX_76802 
/50-Washington-St 
49220-Sunrose-Ln_Palm-Desert_CA_92260 
201-Grandview-Dr_Early_TX_76802 
50-Washington-St 
+0

什么是规则,模式? –

+0

你想要匹配什么? –

+0

@NickolayKondratenko我想匹配这两个字符串。即带有连字符的字符串,也带有下划线和末尾的数字字符串 – rubyist

回答

5

您可以修复的正则表达式像

/^\/?([0-9]+)-(.+?)-(\w+)$/ 

或整个(介意^线匹配匹配 start和$以Ruby正则表达式结束):

/\A\/?([0-9]+)-(.+?)-(\w+)\z/ 

Rubular demo

图案的详细资料

  • \A - 字符串开头
  • \/? - 可选/
  • ([0-9]+) - 第1组:一个或多个数字
  • - - 一个 连字符
  • (.+?) - 组2:比换行符字符其他
  • -一个或多个字符 - 连字符
  • (\w+) - 第3组:一个或多个单词([A-Za-z0-9_])字符
  • \z - 字符串的结尾。
+0

Stribizew但它没有通过“/ 50-Washington-St”与你的正则表达式 – rubyist

+0

为什么要这样呢?它不像你的问题中的字符串。但是你可以在'^'或'\'之后加''W *'(如果你想在开始时允许任意数量的非单词字符)或'\ /?'(只允许一个可选的'/' A'。 –

+0

好的。对不起,这是错字错误 – rubyist

0

我想提出一种解决像这样的问题的方法。主要的任务是可以用与其他Ruby代码相同的方式构造复杂的正则表达式:创建可轻松测试的小代码模块,然后组合这些模块。

考虑必须匹配正则表达式的第一个字符串。

s = "201-Grandview-Dr_Early_TX_76802" 

与此字符串不包含字符需要进行转义,我们可以创建一个正则表达式,将正好由仅仅用斜杠替换双引号并添加启动的字符串此字符串匹配(\A)和结束串(\z)主播:

r = /\A201-Grandview-Dr_Early_TX_76802\z/ 
    #=> /\A201-Grandview-Dr_Early_TX_76802\z/ 
s =~ r 
    #=> 0 

这是我们所拥有的:

/\A201-Grandview\-Dr_Early_TX_76802\z/ 
    ⬆︎street number 
      ⬆︎street name 
        ⬆︎street name suffix 
         ⬆︎city 
          ⬆︎state 
           ⬆︎zip 

想必正则表达式应该垫查找字符串当且仅当字符串包含这六个字段中的每一个的允许值并在相邻字段之间显示格式。

让我们先为六个字段中的每一个规定一个单独的正则表达式。自然,所有这些正则表达式可能都需要进行修改以适应需求。

门牌号码

典型街道数字可能是 “221”, “221B”, “221B”。假设我们也可能有“A19”或“221BZ”而不是“221-B”。然后,我们可能会这样写:

number = /[[:alnum:]]+/ 

(在Regexp搜索“POSIX”)

街道名称

我假设的街道名称由一个分隔的单个词或多个单词的单个空格,其中每个单词都是小写,除了首字母大写。

street = /[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*/ 

/[[:upper:]][[:lower:]]+的第一个字相匹配,(?:\s[[:upper:]][[:lower:]])*的空间,随后通过一个大写字相匹配时,重复零次或更多次((?:...)是非捕获基团。尾随*装置重复零次或多次。)

街道名称后缀

我承担的街道名称后缀(如,“街”,“圣“)是一个字,除了第一个字符,这是大写,任选一个周期结束全部小写:

suffix = /[[:upper:]][[:lower:]]+\.?/ 

我假定城市的名字有相同的要求做的街道名称:

city = street 
    #=> /[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*/ 

国家

个国家由两个大写字母给出:

state = /[[:upper:]]{2}/ 

我们可以通过书面形式更精确:

state = Regexp.union %w| AL AK AZ ... | 

但后来我们不得不每一个领土成为一个新的状态或时间进行更新(可能是由于最近的事件)一个国家从工会中脱身。

邮编

邮政编码是五位数字或九个数字与第一四位数字之后的破折号或连字符。

zip = /\d{5}(?:-\d{4})?/ 

使用

/\A201-Grandview-Dr_Early_TX_76802\z/ 

为我们的模式,我们的整体正则表达式因此如下:

r1 =/
    \A # match start of string 
    #{number} 
    - 
    #{street} 
    - 
    #{suffix} 
    _ 
    #{city} 
    _ 
    #{state} 
    _ 
    #{zip} 
    \z # match end of string 
    /x # free-spacing regex definition mode 
    #=>/
    # \A # match start of string 
    # /(?-mix:[[:alnum:]]+) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+\.?) 
    # _ 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # _ 
    # (?-mix:[[:upper:]]{2}) 
    # _ 
    # (?-mix:\d{5}(?:-\d{4})?) 
    # \z # match start of string 
    /x 

让我们试试它的第一个字符串和变体:

"201-Grandview-Dr_Early_TX_76802" =~ r1 
    #=> 0 
"221B-Grand View-Dr._El Paso_TX_76802-0000" =~ r1 
    #=> 0 
"2A0B1-Grandview-Dr_Early_ZZ_76802" =~ r1 
    #=> 0 
"201-GrandView-Dr_Early_TX_76802" =~ r1 
    #=> nil 
"201-Grandview-Dr_Early_TX_7680" =~ r1 
    #=> nil 
"201-Pi11ar-St_Early_TX_76802" =~ r1 
    #=> nil 
"I live at 201-Grandview-Dr_Early_TX_76802" =~ r1 
    #=> nil 
"201-mg Circle-Lane_Early_TX_76802" =~ r1 
    #=> nil 

现在考虑第二个为此应该有一个匹配的字符串,例如:

"/50-Washington-St" 

我们看到了正则表达式这简直是

r2 =/
    \A 
    \/ 
    #{number} 
    - 
    #{street} 
    - 
    #{suffix} 
    \z 
    /x 
#=>/
# \A 
# \/ 
# (?-mix:[[:alnum:]]+) 
# - 
# (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
# - 
# (?-mix:[[:upper:]][[:lower:]]+\.?) 
# \z 
# /x 

让我们试试吧。

"/50-Washington-St" =~ r2 
    #=> 0 
"50-Washington-St" =~ r2 
    #=> nil 
"/50-Washington-St_Early" =~ r2 
    #=> nil 

所以,现在我们的整体正则表达式是简单

r = Regexp.union(r1,r2) 
    #=> /(?x-mi: 
    # \A # match start of string 
    # (?-mix:[[:alnum:]]+) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+\.?) 
    # _ 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # _ 
    # (?-mix:[[:upper:]]{2}) 
    # _ 
    # (?-mix:\d{5}(?:-\d{4})?) 
    # \z # match end of string 
    # )|(?x-mi: 
    # \A 
    # \/ 
    # (?-mix:[[:alnum:]]+) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+(?:\s[[:upper:]][[:lower:]]+)*) 
    # - 
    # (?-mix:[[:upper:]][[:lower:]]+\.?) 
    # \z 
    # )/ 

"201-Grandview-Dr_Early_TX_76802" =~ r 
    #=> 0 
"/50-Washington-St" =~ r 
    #=> 0