使用正则表达式匹配第 N 次出现

Matching Nth Occurrence with Regex

我正在尝试解析一个字符串并使用正则表达式匹配第 n 次出现。我目前正在处理的示例是提取字符串中的第三个美元值。现在这可能是字符串中的第二个或第四个或第 n 个值,但下面的示例具体是第三个美元值。

字符串:,233.65 ,073.64 ,307.29 ,273.41 [=10=].00 [=10=].00 .88
我尝试匹配的值:,307.29
到目前为止我想出的正则表达式:(?<=$)\S+

到目前为止,代码匹配美元符号后的每个值,所以问题是,如何获取第三个(或第 n 个)值?

从命令行使用 GNU grep 和 libpcre:

$ echo ',233.65 ,073.64 ,307.29 ,273.41 [=10=].00 [=10=].00 .88' \
    |grep -Po '^(?:[^$]*$){3}\K\S+'
9,307.29

(Explanation at Regex101) 这使用可变宽度的正后视,并非所有语言都支持,如 \K 所简化(foo\Kbar 等同于 (?<=foo)bar, 匹配来自 "foobar" 的 "bar")。这会跳过两个美元金额(它使用 {3} 因为我们还包括前导 $ 因为它不是所需匹配的一部分)然后匹配下一个非白色-space 字符.

您可以在 Javascript 中使用相同的逻辑:

let test = ",233.65 ,073.64 ,307.29 ,273.41 [=11=].00 [=11=].00 .88";
test.match(/^(?:[^$]*$){3}(\S+)/)[1];  // "9,307.29"

这基本上是相同的正则表达式 (explanation at Regex101),但我没有在匹配前使用 \K,而是在第一个捕获组中得到了所需的部分,match() 保存在数组索引 1 中(索引 0 是整个匹配项,包括前导部分,因为我们没有使用 …\K(?<=…) 使其宽度为零)。

但是,如果您使用的是像 Javascript 这样的编程语言,您最好还是以编程方式进行:

let test = ",233.65 ,073.64 ,307.29 ,273.41 [=12=].00 [=12=].00 .88";
test.match(/$\S+/g)[2].substring(1);  // "9,307.29"

(Explanation at Regex101) 这是更多的非正则表达式代码,但更清晰。在这里,我只是在寻找美元值,抓住第三个(回想一下数组是零索引的),并使用 substring() 去除前导 $ (字符串也是零索引的) .

注意,Javascript does not support look-behinds 喜欢 …\K(?<=…)