Заменить слово несколькими строками с помощью sed?

Я работаю над bash - script, который должен подготовить E-Mail для отправки пользователю.

Он объединяет некоторые данные, которые заканчиваются несколькими строками. Для примера, хранящегося в $DATA.

Теперь, после немного stfw, я нашел несколько вещей, таких как sed -ei "s/_data_/${DATA}/g" mail.tpl, а также sed заменить переменной несколькими строками. Ни один из них не работает.

Теперь возникает вопрос: как мне получить sed, чтобы заменить что-то несколькими строками текста?

(Альтернативы sed также приветствуются!)

Ответы

Ответ 1

Если вы создаете свой текст с несколькими строками с помощью "\n", это будет работать с простой командой sed как:

DATA=`echo ${DATA} | tr '\n' "\\n"`
#now, DATA="line1\nline2\nline3"
sed "s/_data_/${DATA}/" mail.tpl

Ответ 2

Вы можете сделать это с помощью AWK, используя подстановку переменных. Мы можем установить переменную в AWK, используя -v, а затем использовать функцию AWK gsub чтобы заменить все вхождения регулярного выражения этой переменной.

Например, если файл test имеет следующее содержимое...

foo
bar
blah _data_and_data_
foo
_data_ foobar _data_ again

... а переменная Bash $DATA - это...

1
2
3
4
5

... затем awk -v r=$DATA '{gsub(/_data_/,r)}1' test заменяет все вхождения регулярного выражения _data_ в test файла содержимым $DATA, что приводит к следующему:

foo
bar
blah 1
2
3
4
5and1
2
3
4
5
foo
1
2
3
4
5 foobar 1
2
3
4
5 again

Ответ 3

Я попробовал его и sed 's/pattern/\na\nb\nc/g', но он не работает во всех системах. То, что работает, помещает \, за которым следует новая строка в шаблоне замены, например:

sed 's/pattern/a\
b\
c/g'

Это добавляет строку, содержащую b, и строку, содержащую c, когда шаблон отображается.

Чтобы поместить его в переменную, используйте двойную обратную косую черту:

export DATA="\\
a\\
b\\
c"

а затем:

sed "s/pattern/${DATA}/g"

Обратите внимание на двойные кавычки.

Ответ 4

Я бы предложил просто заменить sed на команду perl следующим образом:

perl -i.bak -pe 's/_data_/$ENV{"DATA"}/g' mail.tpl 

Ответ 5

Ответ на вызов кольца не помог мне; Я думаю, что использование tr не так, и способ, которым он был написан, он просто удаляет новые строки с помощью echo.

Вместо этого я использовал sed. Я использовал код из другого ответа для замены новых строк (кредит: Zsolt Botykai). Я также ожидал, что на моем входе появятся знаки доллара ($), поэтому я тоже позаботился об этом. Возможно, вам придется добавить другую обработку ввода. Обратите внимание на использование двойных кавычек в echo для сохранения новых строк.

DATA="$(cat whatever)"
ESCAPED_DATA="$(echo "${DATA}" | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/\$/\\$/g')"

Затем вы можете использовать ${ESCAPED_DATA} в sed:

cat input | sed 's/one liner/'"${ESCAPED_DATA}"'/' > output 

Просто подумал, что я поделюсь.

Ответ 6

Эхо-переменная во временный текстовый файл.

Вставьте текстовый файл в mail.tpl и удалите данные из mail.tpl

echo ${DATA} > temp.txt    
sed -i -e "/_data_/r temp.txt" -e "//d" mail.tpl

Ответ 7

Сброс всех новых строк с помощью \ (кроме последнего) работал на меня. Последнюю новую строку нельзя экранировать, чтобы не разорвать команду s.

Пример:

DATA="a
b
c"

ESCAPED=$(echo "${DATA}" | sed '[email protected][email protected]\\@g')
echo "${ESCAPED}" 
a\
b\
c

sed "s/pattern/${ESCAPED}/" file

Ответ 8

Вы можете поместить свои данные в файл temp и запустить:

$ sed '/_data_/r DATA_FILE' mail.tpl | sed '/_data_/d'> temp; mv temp mail.tpl

Ответ 9

Не уверен, что вы попытались поместить "\n" в заменяемую часть

sed 's/[pattern]/\
[line 1]\n\
[line 2]\n\
[line n]\n\
/g' mail.tpl

В первой строке есть /\ для удобства чтения. Каждая строка после этого представляет собой отдельную строку, подобную той, которую вы найдете в текстовом редакторе. Последняя строка является автономной, еще раз для удобства чтения. Вы можете сделать все это, если нужно. Работает на Debian Jessie, когда я его тестировал.