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 ksh
、ksh93
(Illumos sh
)、zsh
和 bash
您正在尝试使用错误的工具。 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}
.
由于 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 ksh
、ksh93
(Illumos sh
)、zsh
和 bash
您正在尝试使用错误的工具。 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}
.