您可以使用正則表達式來找到所有的數字,與他們分隔符:
re = /\A(.+?)\s+((?:\d+[a-z]*[,\s]+)*\d+[a-z]*)/
txt = "Sokolov 19, 20, 23 ,25
Hertzl 80,82,84,86
Hertzl 80a,82b,84e,90
Aba Hillel Silver 2,3,5,6,
Weizman 8
Ahad Ha'am 9 13 29"
matches = txt.lines.map{ |line| line.match(re).to_a[1..-1] }
p matches
#=> [["Sokolov", "19, 20, 23 ,25"],
#=> ["Hertzl", "80,82,84,86"],
#=> ["Hertzl", "80a,82b,84e,90"],
#=> ["Aba Hillel Silver", "2,3,5,6"],
#=> ["Weizman", "8"],
#=> ["Ahad Ha'am", "9 13 29"]]
上述正則表達式表示:
\A
在字符串
(…)
奪的前開始結果
.+?
查找一個或多個字符,少至po可以讓這個模式的其餘部分相匹配。
\s+
隨後由一個或多個空格字符(我們不捕捉)
(…)
捕獲結果
(?:…)*
查找零個或更多的什麼在這裏,但沒有捕獲它們
\d+
一個或多個數字(0-9)
[a-z]*
零個或多個小寫字母
[,\s]+
個一個或多個逗號和/或空格字符
\d+
由一個或多個數字
[a-z]*
和零個或多個小寫字母 其次
但是,如果你想打破數成您需要使用scan
或split
或同等產品。
result = matches.map{ |name,numbers| [name,numbers.scan(/[^,\s]+/)] }
p result
#=> [["Sokolov", ["19", "20", "23", "25"]],
#=> ["Hertzl", ["80", "82", "84", "86"]],
#=> ["Hertzl", ["80a", "82b", "84e", "90"]],
#=> ["Aba Hillel Silver", ["2", "3", "5", "6"]],
#=> ["Weizman", ["8"]],
#=> ["Ahad Ha'am", ["9", "13", "29"]]]
這是因爲在重複組內捕獲正則表達式不捕獲每個重複。例如:
re = /((\d+))+/
txt = "hello 11 2 3 44 5 6 77 world"
p txt.match(re)
#=> #<MatchData "11 2 3 44 5 6 77 " 1:"77 " 2:"77">
整個正則表達式匹配整個字符串,但每個捕獲只保存最後看到的實例。在這種情況下,外部捕獲只獲得「77」,內部捕獲只獲得「77」。
爲什麼你不喜歡使用scan
?這是它的目的。
是否有你可以有一個給定名稱的街道號碼的數量有限制嗎? –
街道名稱中是否有數字? IE「3rd Street」或「5th Ave」? – AGS
第三個例子中的'84e'怎麼處理? – Walls