2015-12-16 3 views
2

Я бы хотел использовать sed для этого решения, если это возможно. Вот моя ситуация:sed добавить многострочную строку после сопоставления строки с одной строкой

У меня есть многострочная строка, которая будет передана sed внешними средствами - вероятно, скрипт оболочки или скрипт bash. Строка выглядит следующим образом:

$string = 'blah blah blah\nblahblah\nblah blah blah\n\n' 

Я хотел бы запустить sed команду, которая присоединяет эту строку после того, как найдено совпадение -

sed -i "/^\[org\/gnome\/login-screen\]/a banner-message-text='$string'" /etc/dconf/db/gdm.d/00-mybanner 

Проблема заключается в том, что sed интерпретирует \n символы как символ новой строки , Обратите внимание, что я понимаю, что способ, которым я объявляю переменную $string внутри команды sed, может различаться в зависимости от того, как она выполняется, но даже при вводе строки в командной строке получается многострочный вывод. Таким образом, файл становится похожим:

[org/gnome/login-screen] 
banner-message-text='blah blah blah 
blablah 
blah blah blah 

' 
banner-message-enable=true 

Это вызывает dconf update бросить ошибку. Я надеюсь, чтобы получить файл, чтобы выглядеть следующим образом:

[org/gnome/login-screen] 
banner-message-text='blah blah blah\nblablah\nblah blah blah\n\n' 
banner-message-enable=true 

Но я не могу показаться, чтобы получить sed, чтобы остановить себя от интерпретации \n «с. Спасибо!

EDIT - Полного контекст с внедренным решением (@ том- Фенек) с использованием кукол:

$banner_msg = 'blah blah blah\nblahblah\nblah blah blah\n\n' 

    $comply_cmd = "find /etc/dconf/db/gdm.d -maxdepth 1 -type f -print0 | xargs -0 sed -i '/^banner-message-text=/d' || /bin/true && \ 
    (grep -q \"^\[org/gnome/login-screen\]\" /etc/dconf/db/gdm.d/99-banner && \ 
    sed -i \"/^\[org\/gnome\/login-screen\]/a banner-message-text='\$(printf '%q' \"${banner_msg}\")'\" /etc/dconf/db/gdm.d/99-banner) || \ 
    (echo -e \"\n\[org/gnome/login-screen]\" >> /etc/dconf/db/gdm.d/99-banner && \ 
    echo \"banner-message-text='${banner_msg}'\" >> /etc/dconf/db/gdm.d/99-banner)" 

    $unless_cmd = "grep -q \"^banner-message-text='\$(printf '%q' \"${banner_msg}\")'$\" /etc/dconf/db/gdm.d/99-banner" 

    exec { 'gdm-banner-msg': 
    path  => '/sbin:/bin:/usr/sbin:/usr/bin', 
    umask => '022', 
    provider => shell, 
    command => $comply_cmd, 
    unless => $unless_cmd, 
    notify => Exec['dconf-update'], 
    } 

Спасибо вам всем!

+0

http://unix.stackexchange.com/questions/140763/replace-n-by-a-newline-in-sed-portable – user3159253

+0

Все три ответа были полезны, но я выбрал @ tom-fenech, потому что он логично и последовательность команд более сложна, чем размещена. Используя его тактику, я могу установить одну переменную '$ string' с нормальными escape-последовательностями и использовать' printf '% q'', когда мне нужно запустить 'grep' или' sed', но также использовать оригинал, когда мне нужно запустить 'echo' или' echo -e'. – liberteh

ответ

2

Использование printf с форматом %q спецификатора. Это заботится о ускользающей для вас:

$ echo "$string" 
blah blah blah\nblahblah\nblah blah blah\n\n 
$ printf '%q' "$string" 
blah\ blah\ blah\\nblahblah\\nblah\ blah\ blah\\n\\n 

От man bash:

%q, вызывает printf вывести соответствующий аргумент в формате , которые могут быть повторно использованы в качестве входных данных оболочки.

Это означает, что пробелы также имеют обратную косую черту, но это не наносит вреда.

Тестирование это:

$ cat file 
[org/gnome/login-screen] 
$ sed "/^\[org\/gnome\/login-screen\]/a banner-message-text='$(printf '%q' "$string")'" file 
[org/gnome/login-screen] 
banner-message-text='blah blah blah\nblahblah\nblah blah blah\n\n' 
+1

Вы просто убедили меня более подробно ознакомиться с спецификаторами формата 'printf'. Спасибо за этот камень! – joepd

+0

Это действительно круто! Спасибо! – liberteh

1

Вам нужно бежать ваши обратные слэши:

$ string='blah blah blah\\nblahblah\\nblah blah blah\\n\\n' 
$ echo $string 
blah blah blah\\nblahblah\\nblah blah blah\\n\\n 
$ cat foo.txt 
foo 
baz 
test 

$ sed -i "/^foo/a bar='$string'" foo.txt 
$ cat foo.txt 
foo 
bar='blah blah blah\nblahblah\nblah blah blah\n\n' 
baz 
test 

$ 
1

Подготовка исходного файла конфигурации:

echo -e "[org/gnome/login-screen]\nbanner-message-enable=true"> /etc/dconf/db/gdm.d/00-mybanner 
cat /etc/dconf/db/gdm.d/00-mybanner 

[org/gnome/login-screen] 
banner-message-enable=true 

Вставить новый баннер сообщение без интерпретации \ п символов:

string='blah blah blah\\nblahblah\\nblah blah blah\\n\\n'; sed -i "/^\[org\/gnome\/login-screen\]/a banner-message-text=\'$string\'" /etc/dconf/db/gdm.d/00-mybanner 

Смотрите результат:

cat /etc/dconf/db/gdm.d/00-mybanner 

[org/gnome/login-screen] 
banner-message-text='blah blah blah\nblahblah\nblah blah blah\n\n' 
banner-message-enable=true 

Дело в том, что: положить один дополнительная косая черта перед каждый \ n в вашей строке. Это не позволит sed интерпретировать символ \ n.

+0

Спасибо, я сделал некоторые эксперименты с этой целью, и результаты между установкой строки внутри bash и установкой ее внутри марионетки были непротиворечивыми. Я добавлю дополнительную информацию по этой теме на мой вопрос выше. – liberteh

Смежные вопросы