Как выйти из незавершенных символов с sed?

Я хотел бы использовать sed для выхода из всех незавершенных случаев символа скажите "и" в строке, содержавшейся в переменной text. То, что я делаю,

text='one&two\&three'
sed 's/\([^\\]\)&/\1\\&/g' <<< "${text}"

и я ожидаю, что вывод будет one\&two\&three. Однако то, что я получаю,

one\e&two\&three

Что я (пробуют к) делаю:

  • шаблон поиска \([^\\]\)& должен соответствовать любому возникновению & не предшествовавший обратной косой чертой и хранилищем символ, который предшествует & в \1
  • шаблон замены \1\\& должен поместить промежуточную обратную косую черту & и предыдущий символ, однако это действует как \\\1& по некоторой странной причине

Что я делаю неправильно здесь?

2
задан 14 October 2016 в 19:51

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
4
ответ дан 2 December 2019 в 02:16

Другие вопросы по тегам:

Похожие вопросы: