Sed поиск и замена строк, содержащих/

Мне трудно понять, как использовать sed для поиска и замены строк, содержащих символ / в текстовом файле /etc/myconfig.

Например, в моем существующем текстовом файле у меня есть:

myparam /path/to/a argB=/path/to/B xo

и я хочу, чтобы это было заменено на:

myparam /path/to/c argB=/path/to/D xo

Я попытался сделать это в bash:

line='myparam /path/to/a argB=/path/to/B xo'
line_new='myparam /path/to/c argB=/path/to/D xo'
sed -i 's/$line/$line_new/g' /etc/myconfig

Но ничего не происходит.

Попытка

grep -rn "$line" /etc/myconfig

возвращает меня 'myparam /path/to/a argB=/path/to/B xo'.

Каков правильный способ выражения моей команды sed для выполнения этого поиска и замены и правильной работы с командой /? (Я считаю, что символ / в моих строках - это те, которые дают мне проблему, потому что я использовал аналогичную команду sed для поиска и замены другой строки в текстовом файле без проблем, и эта строка не имеет /.

Ответ 1

Не избегайте обратных косых черт; вы смутитесь. Используйте другой символ после команды s, которая не отображается в тексте (я использую % в примере ниже):

line_old='myparam /path/to/a argB=/path/to/B xo'
line_new='myparam /path/to/c argB=/path/to/D xo'
sed -i "s%$line_old%$line_new%g" /etc/myconfig

Кроме того, вставьте всю строку в двойные кавычки; использование одинарных кавычек означает, что sed видит $line (в оригинале) вместо расширенного значения. Внутри одинарных кавычек нет расширения и метасимволов нет. Если ваш текст может содержать почти любой символ обычного текста, используйте в качестве разделителя контрольный символ (например, control-A или control-G).

Обратите внимание, что использование -i здесь отражает то, что находится в вопросе, но предполагает использование GNU sed. BSD sed (также найденный в Mac OS X) требует наличия суффикса. Вы можете использовать sed -i '' … для замены in situ; что не работает с GNU sed. Чтобы быть переносимым между двумя, используйте -i.bak; который будет работать с обоими - но дает вам файл резервной копии, который вы, вероятно, захотите удалить. Другие платформы Unix (например, AIX, HP-UX, Solaris) могут иметь варианты sed, которые вообще не поддерживают -i. Спецификация POSIX не требуется для sed.

Ответ 2

Это может сработать для вас:

sed -i "s|$line|$line_new|g" /etc/myconfig

Вы должны использовать ", чтобы интерполировать $line и $new_line. Также используйте | или любой символ, который не найден в строке соответствия или замены в качестве разделителя.