2017-03-15 62 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+)/ 

這裏我們使用不字符類來獲得