sed,如何用两行替换一行?

16

我正在尝试在Debian中使用sed将一行替换为两行,以下是我的代码:

sed -i 's/You are good/You are good\n You are the best/g' /output.txt

然而,当我这样做时,sed一直抱怨说“s的选项未知”。


忘了提到,这是一个 shell 脚本,环境是 Debian 6。 - AZhu
3
就是一个一般的评论,我建议在sed中使用#作为分隔符而不是/,这是一个普遍规则。偶尔你会想要在编辑包含#的文件或流时使用/作为分隔符(例如在bash脚本的注释中)。但更常见的情况是(至少根据我的经验),你会编辑没有#但有/作为Linux目录列表的文本。如果你使用井号作为分隔符,你就不必担心分隔问题(尽管仍然需要遵循其他分隔规则)。这里有个简单的例子:echo '/a/' | sed -e 's#/a/#//#g'echo '/a/' | sed -e 's/\/a\//\/\//g'相比。 - Jason R. Mick
1
关于分隔符的赞扬 - 我已经推动这个问题多年了 - 不幸的是,你所见到的每个sed示例都使用/作为分隔符 - 这是选择最不方便的字符。好吧,鉴于你可以使用任何字符,'e'可能更糟糕 - sed 'sesom\estring with an \ee/\el\ephantsee' - Graham Nicholls
3个回答

17

如果你在bash中,可以尝试这个:

sed -i.bak $'s/You are good/You are good\\\nYou are the best/g' /output.txt

奇怪吧?但似乎有效。也许sed不能正确处理换行符,所以需要用另一个反斜杠进行转义,因此是\\,在进入sed之前它将变成单个\

还要注意,您没有向-i传递扩展名。


编辑

刚发现另一种解决方案。由于要将换行符转义后传递给sed(否则它会认为是命令终止符),因此可以实际上使用单引号和回车,只需在输入换行符之前插入反斜杠即可。

$ echo test | sed 's/test/line\
> line'
line
line

17

或者,可以使用搜索并追加 (a 命令) 代替搜索和替换 (s 命令)

sed -i '/Your are good/a You are the best' filename

哦,这很不错,我不知道有这种sed功能。方便! - Jason R. Mick
3
我该如何在新行前添加空格?比如我正在编辑一个YAML文件。 - HVNSweeting
@HVNSweeting sed '/xx/a \ \ yy'(用于插入两个空格) - undefined

1

编辑:

目前我最喜欢的方法是使用特殊字符代替 '\n'。当你传递字符串时,引用规则变得非常棘手。但是,如果你将字符串打包,比如用 | 代替 \n,用 _ 代替 <br>,那么你就有了一个真正可移植的表示形式,可以传递给函数等。

以下是一个示例:

whatAmI=$( printf "Wow oh wow\nYou are good\n"| \
             sed -e 's#\(You are \)\(good\)#\1\2|\1the best#g' | \
             tr '\n' '|' | tr ' ' '_' )

结果:

哇_哦_哇|你很棒|你是最棒的|

要“解压缩”您压缩的字符串,只需通过相同的,但顺序相反即可。

也就是说:

echo "$whatAmI" | tr '|' '\n' | tr '_' ' '

结果

哇塞
你很棒
你是最好的


除了上述的策略(使用appen--/a和使用\\\n作为分隔符),您还可以做到这一点:
sed -i 's/You are good/You are good'"\n"' You are the best/g' /output.txt

在某种程度上,我更喜欢Glenn Jackman的解决方案,因为它更符合原意。

但我发现这种策略很有用,因为你也可以在bash脚本中传递变量。如果你不会多次使用一个变量,那么这比使用-v更加简洁,例如:

whatYouAre="okay"
sed -i 's/You are good/You are good'"\n"' You are '"${whatYouAre}"'/g' /output.txt

(注意:单引号也适用于\n,但不适用于传递变量,因为它需要解释。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接