使用正则表达式匹配第 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
或 (?<=…)
我正在尝试解析一个字符串并使用正则表达式匹配第 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
或 (?<=…)