我正在测试一个包含 2 个命令的sed
脚本。第一个命令从输入中删除一行,第二个命令将一行附加到输入的末尾,因此:
$ cat input.txt
Line 1
Line 2
Line 3
$ sed '/Line 1/d;$aAppended line' input.txt
Line 2
Line 3
Appended line
$ sed '/Line 2/d;$aAppended line' input.txt
Line 1
Line 3
Appended line
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好。但是,如果我选择删除的行恰好是输入的最后一行,则脚本中的第二个命令永远不会运行:
$ sed '/Line 3/d;$aAppended line' input.txt
Line 1
Line 2
Run Code Online (Sandbox Code Playgroud)
我了解到sed
一次读取输入行,对每一行“执行”脚本,直到没有更多的行可供读取,因此我的脚本永远不会“完成”(即Appended line
永远不会附加)这一事实说得通。
尽管如此,这对我来说是一个问题(我仍然需要追加Appended line
)。有谁熟悉这个问题,如果是,是否有“标准解决方法”?我认为一种替代方法(删除最后一行然后附加一行)是替换:
$ sed 's/Line 3/Appended line/' file.txt
Line 1
Line 2
Appended line
Run Code Online (Sandbox Code Playgroud)
这是我唯一的选择吗?
d
手册页中的命令sed
:
删除模式空间。开始下一个周期。
由于多个sed
命令按照提供的顺序执行,“开始下一个周期”实际上意味着在删除该行后,它停止执行可能适用于(当前周期的)已删除行的任何后续命令。因此,如果Line 3
是最后一行,并且它被删除,则将开始新的循环,并且不会执行应应用于最后一行的a
pend命令。
为了解决这个问题,只需调换命令的顺序即可。
sed -e '$aAppended line' -e '/Line 3/d'
Run Code Online (Sandbox Code Playgroud)
或者相当于 GNU 特定代码的标准:
sed '$a\
Appended line
/Line 3/d'
Run Code Online (Sandbox Code Playgroud)
这样,文本将被附加到删除之前的 Line 3
最后一行之后(并且循环将结束)。
请注意,a
不会将行附加到模式空间;引用POSIX,它为以后的输出安排文本,文本[...]应在下一次尝试获取输入行 [...] 之前写入标准输出,因此它不受 影响d
,甚至不受影响通过-n
选项。
根据man sed
,这就是d
:
d Delete pattern space. Start next cycle.
Run Code Online (Sandbox Code Playgroud)
您的任务可以通过以下任一方式完成
$ cat input.txt | { sed '/Line 1/d;'; echo "Appended line"; }
$ { sed '/Line 1/d;' input.txt; echo "Appended line"; } # by @terdon
$ SedAppend() { sed '/Line 1/d;' "$1"; echo "Appended line"; }
$ SedAppend input.txt
Run Code Online (Sandbox Code Playgroud)
前提是您确实希望删除包含字符串“Line 1”的所有行。
归档时间: |
|
查看次数: |
817 次 |
最近记录: |