bash 使用sed用多行替换一个单词?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10107459/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Replace a word with multiple lines using sed?
提问by Cobra_Fast
I'm working on a bash-script that has to prepare an E-Mail for being sent to a user.
我正在处理一个 bash 脚本,它必须准备发送给用户的电子邮件。
It aggregates some data, which ends up being multiple lines of stuff. For the example stored in $DATA
.
它聚合了一些数据,最终成为多行内容。对于存储在$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.
现在,经过一些 stfw 之后,我发现了一些类似的东西sed -ei "s/_data_/${DATA}/g" mail.tpl
,并且sed 替换为带有多行的变量。他们都没有工作。
Now the question is, how do I get sed
to replace something with multiple lines of text?
现在的问题是,如何sed
用多行文本替换某些内容?
(Alternatives to sed
are also welcome!)
(sed
也欢迎替代!)
采纳答案by ring bearer
If you build your multiple line text with "\n
"s, this will work with a simple sed
command as:
如果您使用 " \n
"构建多行文本,这将使用一个简单的sed
命令,如下所示:
DATA=`echo ${DATA} | tr '\n' "\n"`
#now, DATA="line1\nline2\nline3"
sed "s/_data_/${DATA}/" mail.tpl
回答by Kent
You can do this with AWK using variable substitution. We can set a variable in AWK using -v
, and then use AWK's gsub
function to substitute all occurrences of a regular expression with that variable.
您可以使用变量替换对 AWK 执行此操作。我们可以在 AWK 中使用 设置一个变量-v
,然后使用 AWK 的gsub
函数将所有出现的正则表达式替换为该变量。
For example, if the file test
has the following contents ...
例如,如果文件test
具有以下内容...
foo
bar
blah _data_and_data_
foo
_data_ foobar _data_ again
... and the Bash variable $DATA
is ...
...而 Bash 变量$DATA
是 ...
1
2
3
4
5
... then awk -v r=$DATA '{gsub(/_data_/,r)}1' test
replaces all occurrences of the regular expression _data_
in the file test
with the contents of $DATA
, resulting in the following:
...然后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
回答by Albert Veli
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/\na\nb\nc/g'
但它不适用于所有系统。什么工作是\
在替换模式中放置一个换行符,如下所示:
sed 's/pattern/a\
b\
c/g'
This appends a line containing b
and a line containing c
when the pattern is seen.
当看到模式时,这会附加一行包含b
和一行包含c
。
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.
注意双引号。
回答by anubhava
I would suggest simply replacing sed with perl command like this:
我建议简单地用 perl 命令替换 sed,如下所示:
perl -i.bak -pe 's/_data_/$ENV{"DATA"}/g' mail.tpl
回答by Yuval
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
.
持戒人的回答对我不起作用;我认为tr
there的用法是错误的,而且它的编写方式只是通过使用echo
.
Instead, I used sed
. I used code from another answerto 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.
相反,我使用了sed
. 我使用另一个答案中的代码来替换换行符(来源:Zsolt Botykai)。我还希望$
在我的输入中有一些美元符号 ( ),所以我也处理了这个问题。您可能需要添加其他输入处理。请注意使用双引号 inecho
来保留换行符。
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
:
然后你可以${ESCAPED_DATA}
在sed
:
cat input | sed 's/one liner/'"${ESCAPED_DATA}"'/' > output
Just thought I'd share.
只是想我会分享。
回答by Ben Pingilley
Echo variable into temporary text file.
将变量回显到临时文本文件中。
Insert text file into mail.tpl and delete datafrom mail.tpl
将文本文件插入到 mail.tpl 并从 mail.tpl 中删除数据
echo ${DATA} > temp.txt
sed -i -e "/_data_/r temp.txt" -e "//d" mail.tpl
回答by Mihai
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
回答by mgraff
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.
用 a 转义所有换行符\
(最后一个除外)对我有用。最后一个换行符不能被转义以免破坏s
命令。
Example :
例子 :
DATA="a
b
c"
ESCAPED=$(echo "${DATA}" | sed '$!s@$@\@g')
echo "${ESCAPED}"
a\
b\
c
sed "s/pattern/${ESCAPED}/" file
回答by lsu_guy
Not sure if you have tried to put "\n" in the replace part
不确定您是否尝试将 "\n" 放入替换部分
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.
出于可读性原因,第一行有 /\。之后的每一行都是一个独立的行,就像您在文本编辑器中找到的那样。最后一行是独立的,再次出于可读性原因。如果需要,您可以制作所有这些一行。当我测试它时在 Debian Jessie 上工作。