为了好玩,我尝试用regex解析网页的一个子集。这很有趣,直到我遇到了下面的问题。我有一个段落如下;
foo: 1, 2, 3, 4 and 5.
bar: 1, 2 and 3.我要做的是,通过应用以下正则表达式,在该段的第一行中以foo:开头获取数字:
foo:(?:\s(\d)(?:,|\sand|\.))+这与上面的字符串匹配,但它只捕获捕获组的最后一次出现,即5。
如何捕捉以foo:开头的段落中的所有数字,直到使用单个正则表达式首次出现.为止。
发布于 2018-03-11 20:11:16
在大多数编程语言中,重复捕获组的数据不是单独存储的,因此不能单独引用它们。这是使用\G锚点的有效原因。\G使匹配从上一次匹配结束的位置开始,或者它将匹配字符串的开头与\A相同。
因此,我们需要它的第一种能力:
(?:foo:|\G(?!\A))\s*(\d+)\s*(?:,|and)?细目:
(?:启动非捕获组。foo:匹配foo:|或\G(?!\A)从上一次比赛结束的位置继续匹配
)末端\s*任意数量的空格字符(\d+)匹配和捕获数字\s*任意数量的白纸字符(?:,|and)?可选,或and此正则表达式将开始匹配在输入字符串中满足foo的情况。然后尝试查找逗号或and前面的以下数字(允许数字周围的空格)。
\K令牌将重置匹配。这意味着它将发送一个信号给引擎,以忘记到目前为止匹配的任何内容(但保留捕获的任何内容),然后将光标留在该位置。
我在Rubular中使用了\K,使结果集没有匹配的字符串,而是捕获到的数字。然而,Rubular的工作方式似乎不同,不需要\K。这根本不是必须的。
发布于 2018-03-11 08:06:28
这个答案只使用一个正则表达式,但无可否认,它做了一些预处理和后置处理。(请给我一点乐趣。我确实认为这里可能有一些教学价值。)
str = "foo: 1, 2, 34, 4 and 5. and 6."
r = /
\d+ # match one or more digits
(?=[^.]+:oof\z) # match one or more digits other than a period, followed
# by ":oof" at the end of the string, in a positive lookahead
/x # free-spacing regex definition mode
str.reverse.scan(r).join(' ').reverse.split
#=> ["1", "2", "34", "4", "5"]步骤如下。
s = str.reverse
#=> ".6 dna .5 dna 4 ,43 ,2 ,1 :oof"
a = s.scan r
#=> ["5", "4", "43", "2", "1"]
b = a.join(' ')
#=> "5 4 43 2 1"
c = b.reverse
#=> "1 2 34 4 5"
c.split
#=> ["1", "2", "34", "4", "5"]如果没有匹配,则返回空数组。
为什么要倒车?这是为了允许我使用一个正的前瞻,它不像正向后,允许可变长度的匹配。
https://stackoverflow.com/questions/49215149
复制相似问题