FreeBSD sed 用换行符和反斜杠代替

FreeBSD sed with newline and backslash in substitute

由于 FreeBSD 中实现的 sed 不支持替换模式中的任何转义序列,我必须使用 "\'$'\n" 来表示换行符和 " '$'\n”。它确实通过“\”支持反斜杠。

不幸的是,将换行符与反斜杠组合在一起会导致我出错。例如,我想在每行 "key:\" 之后添加以制表符和 "line added.\" 开头的行,我写道:

#!/bin/bash
sed -E 's/^key:\$/&\'$'\n'$'\tline added.\/g' file

它给我抛出了一个错误,如:

sed: 2: "s/^key:\$/&\
    line add ...": unterminated substitute in regular expression

如何在 sed 的替代参数中同时使用换行符和反斜杠?

非常感谢!

示例失败,因为最后一段中的引用似乎是无意的。

$'\tline added.\/g'

$'...' 构造评估整个最后一部分,这意味着它处理 \ 留下 sed 命令以 \/g.

结尾

要获得预期的行为,要么终止 C 风格的转义,然后重新启动单引号字符串

$'\t''line added.\/g'

或者转义\

$'\tline added.\\/g'

另一种方法是将整个命令包含在 $'...' 构建。

sed $'s/^key:\$/&\\\\n\tline added.\\/'

一种可移植的替代方法是使用文字字符、换行符和制表符。
(也许有评论澄清它是故意的)

sed 's/^key:\$/&\\
    line added.\/'

为了在 运行 多次时避免重复,需要稍微复杂一点的脚本。
(请注意,如果最后一行 运行,n 将退出脚本)

sed '/^key:\$/ {
    n
    /^  line added\.\$/!i\
    line added.\
}'

$'...' 存在于 FreeBSD sh、MirBSD kshksh93(Illumos sh)、zshbash

您正在尝试使用错误的工具。 sed 用于在各行上进行简单替换,仅此而已。对于其他任何你应该使用 awk.

to add a line starts with a tab and "line added.\" after every line with "key:\" 只是:

awk '{print} /key:\/{print "\tline added.\"}' file

以上内容适用于所有操作系统的所有 awks。

不在之前执行过的后续 运行 上执行此操作将是:

awk -v n='\tline added:\' 'p~/key:\/ && [=11=]!=n{print n} {print; p=[=11=]}'

例如:

$ cat file1
foo
key:\
bar

$ awk -v n='\tline added:\' 'p~/key:\/ && [=12=]!=n{print n} {print; p=[=12=]}' file1 > file2

$ cat file2
foo
key:\
        line added:\
bar

$ awk -v n='\tline added:\' 'p~/key:\/ && [=12=]!=n{print n} {print; p=[=12=]}' file2
foo
key:\
        line added:\
bar

p 表示旧的,n 表示新的。上面的工作只是等到 AFTER key:\ 行插入新行,并且只有在当前行还不是要插入的行时才进行插入。如果关键行可以出现在文件末尾,那么您需要测试关键并在 END 语句中添加新行:END{if (p~/key:\/) print n}.