使用 sed 将匹配项替换为多行字符串

使用 sed 将匹配项替换为多行字符串

可能的重复:
将多行字符串插入另一个字符串

我有一个名为foo.txt包含:


酒吧
巴兹

我想将每次出现的 替换bar为存储在变量中的多行字符串$bar

1
2
3

导致:


1
2
3
巴兹

我可以awk使用以下方法来做到这一点:

回声“$栏”| awk '{
        if(文件名==“-”)
        {
            如果(我!=“”)
            {
                我=我“\n”
            }
            我=我$0
        }
        别的
        {
            if($0 == "酒吧")
            {
                打印我
            }
            别的
            {
                打印
            }
        }
    }'

但是尝试在sed使用中执行相同的操作sed 's/bar/'"$bar"'/' foobar.txt会出现错误:

sed: 1: “s/bar/1
2
3/":替代模式内未转义的换行符

这个问题可以解决吗?

如果有使用其他标准工具更简单的方法来做到这一点,我也想知道。

答案1

在 中sed,换行符必须在命令的右侧转义s,因此您需要编写它:

sed 's/foo/1\
2\
3/g'

一些sed实现还支持(非标准):

sed 's/foo/1\n2\n3/g'

如果$bar要替换,您需要首先在每个换行符之前插入反斜杠。当您这样做时,您还应该在每个斜杠、反斜杠和与号字符之前插入一个反斜杠。

就像是:

bar_escaped=$(printf '%s\n' "$bar" | sed 's,[\/&],\\&,g;s/$/\\/')
bar_escaped=${bar_escaped%?}
sed "s/foo/$bar_escaped/g"

答案2

我所做的是创建一个sed模式文件,然后sed使用指定的文件进行调用,而不是在命令中指定模式,因为您无法在命令行上执行多行操作(即 \n 不合法)。例如

sed -f pattern_file.sed infile.txt

就我而言,我想找到读取的每一行alarm_if_fail: 1并添加application: XYZ到下一行。所以模式文件.sed看起来如下:

1,/^END/{


        s/^alarm_if_fail: 1$/&\
application: XYZ/


}

如果输入文件.txt好像

Unix
Stackexchange

alarm_if_fail: 1

ABC

然后ed -f pattern_file.sed infile.txt就会返回

Unix
Stackexchange

alarm_if_fail: 1
application: XYZ

ABC

相关内容