Команда sed: поиск и замена переменных с символом \ n - PullRequest
0 голосов
/ 27 июня 2018

У меня есть переменные в скрипте bash:

    $string = "The cat is green.\n"
    $line = "Sunny day today.\n"

каждая из этих переменных содержит символ "\ n", как я могу использовать sed для поиска и замены:

    sed 's/$string/$line/g' file.txt

Похоже, это не сработает, если я удалю "\ n" из строк. Sed работает правильно. Если бы у меня был только текст, я мог бы избежать «\ n», добавив обратную косую черту:

    sed 's/"The cat is green.\\n"/"Sunny day today.\\n"/g' file.txt

Как мне удается выполнять поиск / замену, когда переменные содержат "\ n" в них. Спасибо за помощь.

1 Ответ

0 голосов
/ 27 июня 2018

Похоже, вы пытаетесь сопоставить двухсимвольную последовательность \n, в отличие от одиночного символа новой строки, который вместе они представляют в некоторых контекстах. Между ними есть огромная разница.

В качестве примера вы представили

sed 's/$string/$line/g' file.txt

, но это не сработает совсем, потому что ссылки на переменные не раскрываются в одиночных кавычках. Это не имеет ничего общего со значениями переменных оболочки string и line.

Но давайте рассмотрим эти значения:

$string="The cat is green.\n"
$line="Sunny day today.\n"

[лишние пробелы удалены.]

Конечно, проблема, на которой вы сосредотачиваетесь, заключается в том, что sed распознает \n как код для символа новой строки, но у вас также есть проблема в том, что в регулярном выражении символ . соответствует любой символ, поэтому, если вы хотите, чтобы он воспринимался как литерал, его тоже нужно экранировать (в шаблоне, но не в замене). Если вы пытаетесь поддерживать поиск и замену произвольного текста, то вам также нужно экранировать другие символы.

Отвечая на поставленный вопрос (исключая только \n последовательностей), вы можете сделать это:

sed "s/${string//\\n/\\\\n}/${line//\\n/\\\\n}/g"

Форма расширения параметра ${foo//pat/repl} выполняет подстановку шаблона для расширенного значения, но следует помнить, что шаблон (pat) интерпретируется в соответствии с правилами глобализации оболочки, а не как регулярное выражение. Эта конкретная форма заменяет каждый вид узора; Прочтите руководство по bash, чтобы узнать, какие альтернативы соответствуют только первому появлению и / или соответствуют только началу или концу значения параметра. Также обратите внимание на дополнительное удвоение символов \ в подстановке шаблона - их также нужно экранировать для оболочки.

Учитывая ваши определения переменных, эта команда будет эквивалентна этой:

sed 's/The cat is green.\\n/Sunny day today.\\n/g'

Другими словами, именно то, что вы хотели. Однако, опять же, имейте в виду: это не общее решение для произвольного поиска и замены. Если вы хотите , что , то вам нужно изучить руководство sed, чтобы определить, какие символы должны быть экранированы в регулярном выражении, а какие - в замене. Более того, я не вижу способа сделать это с помощью только одной замены шаблона для каждой переменной.

...