匹配ruby中的正则表达式

时间:2016-11-16 09:03:34

标签: ruby regex

我有以下字符串

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

2 个答案:

答案 0 :(得分:5)

您可以修复正则表达式

//initialize sparkcontext and hivecontext
//10 SQL that manipulate large data to run one by one
val sqls = Array("insert overwrite x select a join b on c","foo", "bar"....)
for(i <- 0 to 10) {
 hiveContext.sql(sqls(i)).collect
}

或匹配整个字符串(请注意<dependency> <groupId>com.levigo.jbig2</groupId> <artifactId>levigo-jbig2-imageio</artifactId> <version>1.6.5</version> </dependency> 匹配 start和/^\/?([0-9]+)-(.+?)-(\w+)$/ 行结束于Ruby regex中):

^

请参阅Rubular demo

模式详情

  • $ - 字符串开始
  • /\A\/?([0-9]+)-(.+?)-(\w+)\z/ - 可选的\A
  • \/? - 第1组:一个或多个数字
  • / - 连字符
  • ([0-9]+) - 第2组:除了换行符之外的一个或多个字符
  • - - 连字符
  • (.+?) - 第3组:一个或多个字(-)字符
  • (\w+) - 字符串结束。

答案 1 :(得分: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

当且仅当字符串包含这六个字段中每个字段的允许值并且在相邻字段之间显示格式时,正如此正则表达式应匹配字符串。

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

街道号码

典型的街道号码可能是&#34; 221&#34;,&#34; 221B&#34;,&#34; 221b&#34;。我们可以说我们也可能有#A; A19&#34;或&#34; 221BZ&#34;但不是&#34; 221-B&#34;。然后我们可以写:

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

(在Regexp中搜索&#34; POSIX&#34;。)

街道名称

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

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

/[[:upper:]][[:lower:]]+匹配第一个单词(?:\s[[:upper:]][[:lower:]])*匹配空格后跟大写单词,重复零次或多次((?:...)是非捕获组。尾随{{1}意味着重复零次或多次。)

街道名称后缀

我假设街道名称后缀(例如,&#39; Street&#39;,&#39; St。&#39;)是一个单词,除了第一个字符外都是小写,大写,可选择以句点结尾:

*

城市

我认为城市名称与街道名称具有相同的要求:

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