Я хотел бы использовать sed
для выхода из всех незавершенных случаев символа скажите "и" в строке, содержавшейся в переменной text
. То, что я делаю,
text='one&two\&three'
sed 's/\([^\\]\)&/\1\\&/g' <<< "${text}"
и я ожидаю, что вывод будет one\&two\&three
. Однако то, что я получаю,
one\e&two\&three
Что я (пробуют к) делаю:
\([^\\]\)&
должен соответствовать любому возникновению &
не предшествовавший обратной косой чертой и хранилищем символ, который предшествует &
в \1
\1\\&
должен поместить промежуточную обратную косую черту &
и предыдущий символ, однако это действует как \\\1&
по некоторой странной причинеЧто я делаю неправильно здесь?
Почему Ваша команда перестала работать:
Вы сделали:
sed 's/\([^\\]\)&/\1\\&/g' <<< "${text}"
[^\\]\
соответствия любой символ кроме \
, и помещенный это в подобранную группу 1, затем &
соответствует литералу &
. Таким образом для one&two\&three
, это будет соответствовать e
прежде сначала &
, помещенный это в полученную группу 1. Для &
прежде three
это не будет подобрано как \
прежде &
В замене Вы использовали \1\\&
, таким образом, вывод становится one\e&two\&three
потому что:
\1
заменяется e
\\
s рассматривают как единственный \
. это дает нам e\
до настоящего времени&
будет соответствовать полному соответствию т.е. e&
т.е. &
не будет оставлен, как Вы думалиТак, подобранная часть т.е. e&
заменяется e\e&
Вы получили бы желаемый результат при использовании другого \
прежде &
(Как два \\
сделайте тот \
, таким образом, Вам нужен тот прежде &
также:
sed 's/\([^\\]\)&/\1\\\&/g' <<<"${text}"
Как Ubuntu sed
поддержки ДО (Расширенное регулярное выражение), можно использовать -E
или -r
опция позволить этому избавиться от ()
s при получении:
sed -E 's/([^\\])&/\1\\\&/g' <<<"${text}"
Альтернативный подход:
Во-первых, удаление \
s перед всеми &
s, и затем добавление \
перед всеми &
:
sed -E 's/[\]+(&)/\1/g; s/&/\\&/g'
Это состоит из два sed
операторы:
s/[\]+(&)/\1/g
удаляет все \
s прежде &
в строке (строка)
s/&/\\&/g
добавляет a \
также все &
в строке (строка)
Пример:
% text='one&two\&three'
% sed 's/\([^\\]\)&/\1\\\&/g' <<< "${text}"
one\&two\&three
% sed -E 's/([^\\])&/\1\\\&/g' <<< "${text}"
one\&two\&three
% sed -E 's/[\]+(&)/\1/g; s/&/\\&/g' <<<"$text"
one\&two\&three