Ответ 1
Вам разрешено указывать $n
или $nn
для ссылки на захваченный текст, поэтому вы можете использовать формат $nn
(здесь $01
), чтобы избежать захвата 0
.
cout << regex_replace( "foobar0x1", regex_a, "$010xNUM" ) << endl;
В моем выражении regex_replace используется группа $1 прямо перед символом '0' в заменяющей строке:
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main() {
regex regex_a( "(.*)bar(.*)" );
cout << regex_replace( "foobar0x1", regex_a, "$10xNUM" ) << endl;
cout << regex_replace( "foobar0x1", regex_a, "$1 0xNUM" ) << endl;
}
Вывод:
xNUM
foo 0xNUM
Я пытаюсь получить вывод foo0xNUM
без промежуточных пробелов.
Как защитить имя группы $1 от следующего символа в строке подстановки?
Вам разрешено указывать $n
или $nn
для ссылки на захваченный текст, поэтому вы можете использовать формат $nn
(здесь $01
), чтобы избежать захвата 0
.
cout << regex_replace( "foobar0x1", regex_a, "$010xNUM" ) << endl;
Guvante предоставил решение для этой проблемы.
Однако является ли поведение корректным в соответствии со спецификацией?
Чтобы начать с вывода. Да, решение имеет четко определенное поведение.
Документация format_default
, которая определяет правила ECMA для интерпретации строки формата, указывает на раздел 15.5.4.11 ECMA-262.
Согласно таблице 22 в Раздел 15.5.4.11 спецификации ECMA-262
$n
n-й захват, где n - одна цифра в диапазоне от 1 до 9 и
$n
, не следует десятичной цифрой. Если n ≤ m и n-й захват undefined, используйте вместо этого пустую строку. Если n > m, результат определяется реализацией.
$nn
nnth capture, где nn - двузначное десятичное число в диапазоне от 01 до 99. Если nn ≤ m и nnth-захват undefined, используйте вместо этого пустую строку. Если nn > m, результат определяется реализацией.
Переменная m определена в предыдущем абзаце в том же разделе:
[...] Пусть m - количество скобок слева в скобках в
searchValue
(используяNcapturingParens
, как указано в 15.10.2.1).
"$10xNUM"
Вернуться к коду в вопросе:
cout << regex_replace( "foobar0x1", regex_a, "$10xNUM" ) << endl;
Так как за $1
следует 0
, его нужно интерпретировать как второе правило $nn
, так как первое правило запрещает любую цифру следовать за $n
. Однако, поскольку шаблон имеет только 2 группы захвата (m = 2) и 10 > 2, поведение определяется реализацией в соответствии со спецификацией.
Мы можем увидеть эффект предложения, определяемого реализацией, путем сравнения результата функционально эквивалентного кода JavaScript в Firefox 37.0.1:
> "foobar0x1".replace(/(.*)bar(.*)/g, "$10xNUM" )
< "foo0xNUM"
Как вы можете видеть, Firefox решил интерпретировать $10
как значение первого захвата группы $1
, а затем фиксированную строку 0
. Это допустимая реализация в соответствии со спецификацией при условии в $nn
.
"$010xNUM"
То же, что и выше, используется предложение $nn
, так как предложение $n
запрещает любую цифру. Поскольку 01 in $01
меньше числа групп захвата (m = 2), поведение хорошо определено, что должно использовать содержимое группы захвата 1 при замене.
Поэтому ответ Guvante вернет тот же результат на любой компилятор С++ жалобы.
Я попытался найти метод простого экранирования пространства или чего-то другого, чтобы он не печатался, но я не смог.
Однако бит, который вы пытаетесь добавить, может быть просто добавлен в конец вывода регулярного выражения:
cout << regex_replace( "foobar0x1", regex_a, "$1" ) << "0xNUM" << endl;
Вышеупомянутая строка даст вам нужный результат.