39

我正在研究一个 bash 脚本,该脚本必须准备一封电子邮件以发送给用户。

它聚合了一些数据,最终成为多行内容。对于存储在$DATA.

现在,经过一些 stfw 之后,我发现了一些东西,比如sed -ei "s/_data_/${DATA}/g" mail.tplsed replace with variable with multiple lines。它们都不起作用。

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

sed(也欢迎替代品!)

4

9 回答 9

26

您可以使用 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
于 2012-04-11T14:11:20.477 回答
16

我建议简单地将 sed 替换为 perl 命令,如下所示:

perl -i.bak -pe 's/_data_/$ENV{"DATA"}/g' mail.tpl 
于 2012-04-11T14:31:49.133 回答
15

如果你用 " \n"s 构建你的多行文本,这将使用一个简单的sed命令:

DATA=`echo ${DATA} | tr '\n' "\\n"`
#now, DATA="line1\nline2\nline3"
sed "s/_data_/${DATA}/" mail.tpl
于 2012-04-11T14:13:15.423 回答
11

我试过了,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"

注意双引号。

于 2012-04-11T14:14:20.107 回答
11

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

只是想我会分享。

于 2014-04-06T23:39:32.780 回答
8

将变量回显到临时文本文件中。

将文本文件插入 mail.tpl 并从 mail.tpl 中删除数据

echo ${DATA} > temp.txt    
sed -i -e "/_data_/r temp.txt" -e "//d" mail.tpl
于 2015-10-28T17:52:43.870 回答
3

用 a 转义所有换行符\(最后一个除外)对我有用。不得转义最后一个换行符以免破坏s命令。

例子 :

DATA="a
b
c"

ESCAPED=$(echo "${DATA}" | sed '$!s@$@\\@g')
echo "${ESCAPED}" 
a\
b\
c

sed "s/pattern/${ESCAPED}/" file
于 2018-01-08T17:53:10.547 回答
2

您可以将数据放在临时文件中并运行:

$ sed '/_data_/r DATA_FILE' mail.tpl | sed '/_data_/d'> temp; mv temp mail.tpl
于 2012-04-11T14:19:40.347 回答
1

不确定您是否尝试将“\n”放入替换部分

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

出于可读性原因,第一行有 /\。之后的每一行都是一个独立的行,就像您在文本编辑器中找到的那样。最后一行是独立的,再次出于可读性原因。如果需要,您可以制作所有这一条线。当我测试它时,它可以在 Debian Jessie 上运行。

于 2016-08-02T05:17:29.547 回答