2017-03-15 63 views
0

我的正则表达式没有返回即使模式出现在匹配字符串匹配后不返回任何结果:正则表达式甚至转义特殊字符

regex = /(.+)\\\\n(\w+),\s(\w{2})\s(\d+)/ 
address = "6761 SW 19 St\\nPark City, PA 19020" 
address =~ regex 
=> nil 

我期待一个0的结果,所以我可以用$ 1,$ 2, $ 3为了提取我想要的数据。

我能想象的唯一错误就是转义序列。但是,我是否有权像上面那样逃走?

+0

模块已经存在解析街道地址的郊区,[地理编码](https://github.com/geocommons /地址解析器)。 – Schwern

+0

@Schwern好吧,但正则表达式有什么问题? – Donato

+0

我试过\\\\ n,我试过\\\ n并试过\ n – Donato

回答

3

解析地址是非常棘手的,很容易写出一个过于简单的正则表达式,它不能捕获所有的许多特殊情况,或者试图捕获所有这些特殊情况下的兔子洞。

幸运的是,已经有两个非常完善的模块:GeocoderStreetAddress。我亲自致力于改进StreetAddress。

StreetAddress只是尽可能地解析地址。

2.3.3 :001 > address = "6761 SW 19 St\\\nPark City, PA 19020" 
=> "6761 SW 19 St\\\nPark City, PA 19020" 
2.3.3 :002 > require 'street_address' 
=> true 
2.3.3 :005 > StreetAddress::US.parse(address) 
=> #<StreetAddress::US::Address:0x007fcc62a88ca8 @number="6761", @street="19 St\\", @street_type="Park", @unit=nil, @unit_prefix=nil, @suffix=nil, @prefix="SW", @city="City", @state="PA", @postal_code="19020", @postal_code_ext=nil> 

请注意,它将反斜线保留为街道名称的一部分。地址中的反斜杠非常不正常。你可以用覆盖来改正这个,首先去除反斜线。

地理编码器采用不同的方法对美国人口普查数据进行模糊匹配。安装起来有点困难,但它可以更好地解析真实的街道地址。

使用其中之一,不要写你自己的。我只会将您的代码中的问题作为练习来讨论。


存在多个问题,其中任何一个都会导致匹配失败。这不能通过只是抛出更多的反斜杠,直到碰巧工作。

首先是在地址本身。

address = "6761 SW 19 St\\nPark City, PA 19020" 
         ^

\\n是一个字面反斜杠,后跟字母n。

> address = "6761 SW 19 St\\nPark City, PA 19020" 
=> "6761 SW 19 St\\nPark City, PA 19020" 
> puts address 
6761 SW 19 St\nPark City, PA 19020 

我希望你的意思\\\n这是一个反斜杠后面的字母n。

然后你的正则表达式有多个问题。首先,反斜杠太多了。

/(.+)\\\\n(\w+),\s(\w{2})\s(\d+)/ 
    ^^^^^ 

这是两个字母反斜杠后跟字母n。你需要\\\n

下一个问题是试图匹配“公园城市”,与\w

/(.+)\\\n(\w+),\s(\w{2})\s(\d+)/ 
     ^^^^^^ 

\w是字母和数字,只是下划线,没有空格。您需要改为[\w\s]+

现在,对那个特定的地址“起作用”,但它很脆弱,可能会在其他许多地方失败。


但使用address =~ regex$1而这种情况并非做比赛在Ruby中的最佳途径。而是使用regex.match(address),它返回MatchData对象。然后你可以使用它作为一个数组。 match[0]是匹配的一切。 match[1]$1(即第一次捕捉)等等。

2.3.3 :034 > match[0] 
=> "6761 SW 19 St\\\nPark City, PA 19020" 
2.3.3 :035 > match[1] 
=> "6761 SW 19 St" 
2.3.3 :036 > match[2] 
=> "Park City" 
2.3.3 :037 > match[3] 
=> "PA" 
2.3.3 :038 > match[4] 
=> "19020" 

这避免了使用可能由其它正则表达式被吹到并允许周围传递MatchData对象作为单个单元的变量。

+0

这是最终奏效的正则表达式:/(.+)\\n([\w\s]+),\((\w{2})\s(\d+)/ – Donato

+0

@Donato那“工作”只是因为地址不正确。再次,'\\ n'是一个字面反斜杠,后面跟着一个无意义的n。它应该是'\\\ n',它是一个字面反斜杠,后跟一个换行符。你改变了正则表达式来匹配地址中的错误,而不是修正错误。 ***打印地址***,你会看到。 – Schwern

+0

https://stackoverflow.com/questions/648156/backslashes-in-single-quoted-strings-vs-double-quoted-strings – Donato

0

另一种快速交替的正则表达式:

regex = /(.+)\\n([^,]+),\s(\w{2})\s(\d+)/ 

这里我们使用不字符类来获得