C ++ 11正则表达式:在替换字符串中捕获组后的数字
C++11 regex: digit after capturing group in replacement string
我的 regex_replace 表达式在替换字符串中的“0”字符之前使用组 $1,如下所示:
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main() {
regex regex_a( "(.*)bar(.*)" );
cout << regex_replace( "foobar0x1", regex_a, "xNUM" ) << endl;
cout << regex_replace( "foobar0x1", regex_a, " 0xNUM" ) << endl;
}
输出为:
xNUM
foo 0xNUM
我试图获得没有中间空格的输出 foo0xNUM
。
如何保护组名 $1 不受替换字符串中下一个字符的影响?
我试图找到一种简单地转义 space 之类的方法,这样它就不会打印出来,但我做不到。
但是,您尝试添加的位可以简单地附加到正则表达式输出的末尾:
cout << regex_replace( "foobar0x1", regex_a, "" ) << "0xNUM" << endl;
上面一行会给你你想要的输出。
您可以指定 $n
或 $nn
来引用捕获的文本,因此您可以使用 $nn
格式(此处为 </code>)以避免抓取<code>0
.
cout << regex_replace( "foobar0x1", regex_a, "0xNUM" ) << endl;
Guvante 已经解决了这个问题。
但是,行为是否根据规范明确定义?
从结论说起。 是的,该解决方案具有明确定义的行为。
C++ 规范
format_default
的文档指定了解释格式字符串的 ECMA 规则,指向 ECMA-262 的第 15.5.4.11 节。
ECMA-262 规范
根据 Table 22 在 Section 15.5.4.11 of ECMA-262 specification
$n
The nth capture, where n is a single digit in the range 1 to 9 and $n
is not followed by a decimal digit. If n ≤ m and the nth capture is undefined, use the empty String instead. If n > m, the result is implementation-defined.
$nn
The nnth capture, where nn is a two-digit decimal number in the range 01 to 99. If nn ≤ m and the nnth capture is undefined, use the empty String instead. If nn > m, the result is implementation-defined.
变量m在同一节的上一段中定义:
[...] Let m be the number of left capturing parentheses in searchValue
(using NcapturingParens
as specified in 15.10.2.1).
问题中的替换字符串"xNUM"
回到问题中的代码:
cout << regex_replace( "foobar0x1", regex_a, "xNUM" ) << endl;
由于 </code> 后跟 <code>0
,因此必须将其解释为第二条规则 $nn
,因为第一条规则禁止任何数字跟随 $n
。但是,由于该模式只有 2 个捕获组 (m = 2) 并且 10 > 2,因此根据规范,行为是 实现定义的。
通过比较 Firefox 37.0.1 中功能等效的 JavaScript 代码的结果,我们可以看到实现定义子句的效果:
> "foobar0x1".replace(/(.*)bar(.*)/g, "xNUM" )
< "foo0xNUM"
如您所见,Firefox 决定将 </code> 解释为采用第一个捕获组 <code>
的值,然后是固定字符串 0
。根据规范,在 $nn
子句中的条件下,这是一个有效的实现。
Guvante 回答中的替换字符串:"0xNUM"
同上,使用了$nn
子句,因为$n
子句禁止后面跟任何数字。由于
中的01小于capturing groups的个数(m=2),行为是明确的,即在replacement中使用capturing group 1的内容。
因此,Guvante 的回答将 return 在任何投诉的 C++ 编译器上得到相同的结果。
我的 regex_replace 表达式在替换字符串中的“0”字符之前使用组 $1,如下所示:
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main() {
regex regex_a( "(.*)bar(.*)" );
cout << regex_replace( "foobar0x1", regex_a, "xNUM" ) << endl;
cout << regex_replace( "foobar0x1", regex_a, " 0xNUM" ) << endl;
}
输出为:
xNUM
foo 0xNUM
我试图获得没有中间空格的输出 foo0xNUM
。
如何保护组名 $1 不受替换字符串中下一个字符的影响?
我试图找到一种简单地转义 space 之类的方法,这样它就不会打印出来,但我做不到。
但是,您尝试添加的位可以简单地附加到正则表达式输出的末尾:
cout << regex_replace( "foobar0x1", regex_a, "" ) << "0xNUM" << endl;
上面一行会给你你想要的输出。
您可以指定 $n
或 $nn
来引用捕获的文本,因此您可以使用 $nn
格式(此处为 </code>)以避免抓取<code>0
.
cout << regex_replace( "foobar0x1", regex_a, "0xNUM" ) << endl;
Guvante 已经
但是,行为是否根据规范明确定义?
从结论说起。 是的,该解决方案具有明确定义的行为。
C++ 规范
format_default
的文档指定了解释格式字符串的 ECMA 规则,指向 ECMA-262 的第 15.5.4.11 节。
ECMA-262 规范
根据 Table 22 在 Section 15.5.4.11 of ECMA-262 specification
$n
The nth capture, where n is a single digit in the range 1 to 9 and
$n
is not followed by a decimal digit. If n ≤ m and the nth capture is undefined, use the empty String instead. If n > m, the result is implementation-defined.
$nn
The nnth capture, where nn is a two-digit decimal number in the range 01 to 99. If nn ≤ m and the nnth capture is undefined, use the empty String instead. If nn > m, the result is implementation-defined.
变量m在同一节的上一段中定义:
[...] Let m be the number of left capturing parentheses in
searchValue
(usingNcapturingParens
as specified in 15.10.2.1).
问题中的替换字符串"xNUM"
回到问题中的代码:
cout << regex_replace( "foobar0x1", regex_a, "xNUM" ) << endl;
由于 </code> 后跟 <code>0
,因此必须将其解释为第二条规则 $nn
,因为第一条规则禁止任何数字跟随 $n
。但是,由于该模式只有 2 个捕获组 (m = 2) 并且 10 > 2,因此根据规范,行为是 实现定义的。
通过比较 Firefox 37.0.1 中功能等效的 JavaScript 代码的结果,我们可以看到实现定义子句的效果:
> "foobar0x1".replace(/(.*)bar(.*)/g, "xNUM" )
< "foo0xNUM"
如您所见,Firefox 决定将 </code> 解释为采用第一个捕获组 <code>
的值,然后是固定字符串 0
。根据规范,在 $nn
子句中的条件下,这是一个有效的实现。
Guvante 回答中的替换字符串:"0xNUM"
同上,使用了$nn
子句,因为$n
子句禁止后面跟任何数字。由于中的01小于capturing groups的个数(m=2),行为是明确的,即在replacement中使用capturing group 1的内容。
因此,Guvante 的回答将 return 在任何投诉的 C++ 编译器上得到相同的结果。