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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:55:48  来源:igfitidea点击:

Replace a word with multiple lines using sed?

bashreplacesed

提问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.tpland 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 sedto replace something with multiple lines of text?

现在的问题是,如何sed用多行文本替换某些内容?

(Alternatives to sedare also welcome!)

sed也欢迎替代!)

采纳答案by ring bearer

If you build your multiple line text with "\n"s, this will work with a simple sedcommand 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 gsubfunction to substitute all occurrences of a regular expression with that variable.

您可以使用变量替换对 AWK 执行此操作。我们可以在 AWK 中使用 设置一个变量-v,然后使用 AWK 的gsub函数将所有出现的正则表达式替换为该变量。

For example, if the file testhas the following contents ...

例如,如果文件test具有以下内容...

foo
bar
blah _data_and_data_
foo
_data_ foobar _data_ again

... and the Bash variable $DATAis ...

...而 Bash 变量$DATA是 ...

1
2
3
4
5

... then awk -v r=$DATA '{gsub(/_data_/,r)}1' testreplaces all occurrences of the regular expression _data_in the file testwith 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 band a line containing cwhen 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 trthere is wrong, and the way it's written, it simply strips away newlines by use of echo.

持戒人的回答对我不起作用;我认为trthere的用法是错误的,而且它的编写方式只是通过使用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 echoto 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 scommand.

用 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 上工作。