可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm working on a bash-script that has to prepare an E-Mail for being sent to a user.
It aggregates some data, which ends up being multiple lines of stuff. For the example stored in $DATA
.
Now, after a bit of stfw I found a few things like sed -ei "s/_data_/${DATA}/g" mail.tpl
and also sed replace with variable with multiple lines. None of them work.
Now the question is, how do I get sed
to replace something with multiple lines of text?
(Alternatives to sed
are also welcome!)
回答1:
If you build your multiple line text with "\n
"s, this will work with a simple sed
command as:
DATA=`echo ${DATA} | tr '\n' "\\n"`
#now, DATA="line1\nline2\nline3"
sed "s/_data_/${DATA}/" mail.tpl
回答2:
awk?
kent$ cat test
foo
bar
blah _data_and_data_
foo
_data_ foobar _data_ again
kent$ echo $DATA
1
2
3
4
5
kent$ awk -v r=$DATA '{gsub(/_data_/,r)}1' test
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:
I would suggest simply replacing sed with perl command like this:
perl -i.bak -pe 's/_data_/'"${DATA}"'/g' mail.tpl
回答4:
I tried it and sed 's/pattern/\na\nb\nc/g'
but it does not work on all systems. What does work is putting a \
followed by a newline in the replace pattern, like this:
sed 's/pattern/a\
b\
c/g'
This appends a line containing b
and a line containing c
when the pattern is seen.
To put it in a variable, use double backslashes:
export DATA="\\
a\\
b\\
c"
and then:
sed "s/pattern/${DATA}/g"
Note the double quotes.
回答5:
ring bearer's answer didn't work for me; I think the usage of tr
there is wrong, and the way it's written, it simply strips away newlines by use of echo
.
Instead, I used sed
. I used code from another answer to replace newlines (credit: Zsolt Botykai). I also expected some dollar signs ($
) in my input so I took care of that too. You might need to add other input handling. Note the use of double quotes in echo
to preserve newlines.
DATA="$(cat whatever)"
ESCAPED_DATA="$(echo "${DATA}" | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/\$/\\$/g')"
Then you can use ${ESCAPED_DATA}
in sed
:
cat input | sed 's/one liner/'"${ESCAPED_DATA}"'/' > output
Just thought I'd share.
回答6:
Escaping all the newlines with a \
(except the last one) worked for me.
The last newline must not be escaped not to break the s
command.
Example :
DATA="a
b
c"
ESCAPED=$(echo "${DATA}" | sed '$!s@$@\\@g')
echo "${ESCAPED}"
a\
b\
c
sed "s/pattern/${ESCAPED}/" file
回答7:
You can put your data in a temp file and run:
$ sed '/_data_/r DATA_FILE' mail.tpl | sed '/_data_/d'> temp; mv temp mail.tpl
回答8:
Echo variable into temporary text file.
Insert text file into mail.tpl and delete data from mail.tpl
echo ${DATA} > temp.txt
sed -i -e "/_data_/r temp.txt" -e "//d" mail.tpl
回答9:
Not sure if you have tried to put "\n" in the replace part
sed 's/[pattern]/\
[line 1]\n\
[line 2]\n\
[line n]\n\
/g' mail.tpl
The first line has /\ for readibility reasons. Each line after that is a stand-alone line like you would find in a text editor. Last line is stand-alone, once again for readability reasons. You can make all of this one line if needed. Works on Debian Jessie when I tested it.