[英]Matching repeated pattern in string
我在文件中有街道名称和数字,如下所示:
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
我用正则表达式一一解析。 我想要一个能找到并匹配的正则表达式:
我想出这个意思是:
/(\D{2,})\s+(\d{1,3}[a-d|א-ד]?)(?:[,\s]{1,3})?/
它找到街道名称和第一个数字。 我需要找到所有数字。
如果可能的话,我不想使用两个单独的正则表达式,并且我宁愿不使用Ruby的scan
而只在一个正则表达式中使用它。
您可以使用正则表达式查找所有数字及其分隔符:
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
从字符串的开头开始 (…)
捕捉结果
.+?
找到一个或多个字符,使该模式其余部分匹配的字符尽可能少。 \\s+
后跟一个或多个空格字符(我们不会捕获) (…)
捕捉结果
(?:…)*
在这里找到零个或多个,但不要捕获它们 \\d+
一个或多个数字(0–9) [az]*
零个或多个小写字母 [,\\s]+
一个或多个逗号和/或空格字符 \\d+
后跟一位或多位数字 [az]*
以及零个或多个小写字母 但是,如果您想将数字分成几部分,则需要使用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
? 这就是它的目的。
唯一只能捕获重复表达式的最后一个实例的局限性是,为单个实例编写正则表达式,然后让正则表达式机器为您进行重复,这与全局替换选项一样,诚然类似于scan 。 不幸的是,在这种情况下,你必须匹配着街道名称或门牌号码,然后就没有办法轻易捕获的数字与捕获的名字联系在一起。
正则表达式在其功能方面很出色,但是当您尝试将其应用程序扩展到其自然限制之外时,它并不漂亮。 ;-)
我想要一个能找到并匹配的正则表达式。
digits (0-9)
和撇号以外的其他characters
? a
, b
, c
或d
吗? 以下是一些可能的选项:
如果不确定街道名称包含什么,但知道您的街道号码模式将是带有可选字母,逗号或空格的数字。
/^(.*?)\s+(\d+(?:[a-z]?[, ]+\d+)*)(?=,|$)/
查看工作演示
如果街道名称仅包含带有可选撇号的字母,并且街道编号包含带有可选字母的数字,则逗号。
/^([a-zA-Z' ]+)\s+(\d+(?:[a-z]?[, ]+\d+)*)(?=,|$)/
查看工作演示
如果您的街道名称和街道编号模式始终一致,则可以轻松实现。
/^([a-zA-Z' ]+)\s+([0-9a-z, ]+)$/
查看工作演示
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.