sed使用:预期的上下文地址

lut*_*act 6 bash bsd gnu sed

sed在macOS上使用命令,文本如下:

$ cat pets.txt 
This is my cat
  my cat's name is betty
This is your dog
  your dog's name is frank
This is your fish
  your fish's name is george
This is my goat
  my goat's name is adam
Run Code Online (Sandbox Code Playgroud)

当我运行BSD时,sed它显示一个错误:

$ sed '/dog/,+3s/^/# /g' pets.txt
Run Code Online (Sandbox Code Playgroud)

sed:1:"/ dog /,+ 3s/^ /#/ g":预期的上下文地址

它出什么问题了?当我使用gsed(GNU sed)时,它运行良好:

This is my cat
  my cat's name is betty
# This is your dog
#   your dog's name is frank
# This is your fish
#   your fish's name is george
This is my goat
  my goat's name is adam
Run Code Online (Sandbox Code Playgroud)

Mar*_*eed 9

它适用于GNU sed,因为你正在利用GNU项目添加到sed的一个功能,该功能以前不存在于程序中(并且仍然不在非GNU版本中).

你可以在非GNU sed中获得相同的结果:

sed -E '/dog/{N;N;N;s/(^|\n)/&# /g;}' pets.txt
Run Code Online (Sandbox Code Playgroud)

也就是说,一旦我们看到"狗",也可以拉入接下来的三行.然后#在line(^)开头和所有换行符(\n)之后粘贴一个+空格.为了能够在单个正则表达式中进行搜索和替换,我们需要启用扩展正则表达式,这就是它的-E作用.没有它,我们可以使用两个s命令来完成它,一个用于行的开头,另一个用于换行:

sed '/dog/{N;N;N;s/^/# /;s/\n/&# /g;}' pets.txt
Run Code Online (Sandbox Code Playgroud)

如果您正在寻找另一种方法在没有安装GNU coreutils的股票Mac上执行此操作,您可能想要使用其他实用程序,例如awk:

awk '/dog/ {l=3}; (l-- > 0) {$0="# "$0} 1' pets.txt
Run Code Online (Sandbox Code Playgroud)

或perl(与awk版本相同的想法,只是不同的语法):

perl -pe '$l=3 if /dog/; s/^/# / if $l-- > 0;'  pets.txt  
Run Code Online (Sandbox Code Playgroud)


Jon*_*ler 7

Mac OS X 使用 BSDsed而不是 GNU sed

当您sed在 Mac OS X 上使用 GNU扩展时sed,您会得到不同的结果或失败。

传统上,sed不支持数字偏移,向前或向后。您需要修改脚本才能在 Mac OS X 上运行。

这将适用于给定的数据,但使用fish是可疑的:

sed '/dog/,/your fish/s/^/# /g' pets.txt
Run Code Online (Sandbox Code Playgroud)