搜索并用sed替换多行模式

Moz*_*zzy 5 bash sed

我已经看到了很多有关此问题的示例,但还没有看到适合我使用的示例。尽管我对sed非常熟悉,但我还是很to愧地说我是高级功能的菜鸟。这是眼前的问题。

我有一个多行模式,可以像这样成功地与sed匹配,

sed -e '/Favorite Animals/, /!/p

Favorite Animals
Monkey
Penguin
Cat
!
Favorite Things
Shoe
Dog
Wheel
Moth
!
Run Code Online (Sandbox Code Playgroud)

我个人对此表达的喜好是,我可以将可变数量的行匹配到感叹号。现在假设我想进行搜索并替换相同的模式。基本上,我想用我选择的任何字符串替换以前演示过的多行模式。有任何想法吗?我希望使用与演示的sed命令类似的语法,但是乞g不能成为选择者。

我的想法是,我可以用字符串替换由感叹号分隔的组之一。我称它们为“条目”。我希望能够更新或覆盖这些条目。如果我有喜欢的动物的新更新版本,我希望能够用这样的新条目替换旧条目。

Favorite Animals
Sloth
Platypus  
Badger
Dog
!
Favorite Things
Shoe
Dog
Wheel
Moth
!
Run Code Online (Sandbox Code Playgroud)

如您所见,我现在不再是猴子的粉丝。

Jon*_*ler 5

有多种选择-的ica都可以使用的命令。

修改后的答案

修改后的答案现在处理问题中的修改后的数据文件。这是修改后的data文件的适度增强版本:

There's material at the start of the file then the key information:
Favourite Animals
Monkey
Penguin
Cat
!
Favourite Things
Shoe
Wheel
Moth
!
and some material at the end of the file too.
Run Code Online (Sandbox Code Playgroud)

这三个sed脚本均产生相同的输出:

sed '/Favourite Animals/,/!/c\
Favourite Animals\
Sloth\
Platypus\
Badger\
!
' data

sed '/Favourite Animals/i\
Favourite Animals\
Sloth\
Platypus\
Badger\
!
/Favourite Animals/,/!/d' data

sed '/Favourite Animals/a\
Favourite Animals\
Sloth\
Platypus\
Badger\
!
/Favourite Animals/,/!/d' data
Run Code Online (Sandbox Code Playgroud)

样本输出:

There's material at the start of the file then the key information:
Favourite Animals
Sloth
Platypus
Badger
!
Favourite Things
Shoe
Wheel
Moth
!
and some material at the end of the file too.
Run Code Online (Sandbox Code Playgroud)

所有脚本都必须使用唯一的字符串,/Favourite Animals/并且不要取消重复的尾随上下文,这一点至关重要/!/。如果i还是a使用/!/替代/Favourite Animals/,输出的变化-而不是更好。

/!/i

There's material at the start of the file then the key information:
Favourite Animals
Sloth
Platypus
Badger
!
Favorite Things
Shoe
Wheel
Moth
Favourite Animals
Sloth
Platypus
Badger
!
!
and some material at the end of the file too.
Run Code Online (Sandbox Code Playgroud)

/!/a

There's material at the start of the file then the key information:
Favourite Animals
Sloth
Platypus
Badger
!
Favorite Things
Shoe
Wheel
Moth
!
Favourite Animals
Sloth
Platypus
Badger
!
and some material at the end of the file too.
Run Code Online (Sandbox Code Playgroud)

额外要求

可以使用sed在一个范围内选择一个范围吗?基本上,如果我想在先前指定的范围内更改或删除一个/很多我最喜欢的动物,该怎么办。那是/Favorite Animals/,/!/...在这个范围内的变化。

当然是。对于单个映射:

 sed '/Favourite Animals/,/!/ s/Monkey/Gorilla/'
Run Code Online (Sandbox Code Playgroud)

对于多个映射:

 sed '/Favourite Animals/,/!/ {
      s/Monkey/Gorilla/
      s/Penguin/Zebra/
      s/Cat/Dog/
      }'
Run Code Online (Sandbox Code Playgroud)

如果愿意,还可以将它们合并到一行中-使用分号将它们分开:

 sed '/Favourite Animals/,/!/ { s/Monkey/Gorilla/; s/Penguin/Zebra/; s/Cat/Dog/; }'
Run Code Online (Sandbox Code Playgroud)

请注意,对于最后一个分号的必要性,GNU sed和BSD(Mac OS X)sed有不同的看法-所显示的内容对这两者均适用。


原始答案适用于更简单的输入文件。

原始答案

考虑data包含以下内容的文件:

 sed '/Favourite Animals/,/!/ s/Monkey/Gorilla/'
Run Code Online (Sandbox Code Playgroud)

使用c,您可能会写:

 sed '/Favourite Animals/,/!/ {
      s/Monkey/Gorilla/
      s/Penguin/Zebra/
      s/Cat/Dog/
      }'
Run Code Online (Sandbox Code Playgroud)

使用i,您将使用:

$ sed '/Favourite Animals/i\
> Replacement material\
> for the favourite animals
> /Favourite Animals/,/!/d' data
There's material
at the start of the file
then the key information:
Replacement material
for the favourite animals
and material at the end of the file too.
$
Run Code Online (Sandbox Code Playgroud)

使用a,您可能会写:

$ sed '/!/a\
> Replacement material\
> for the favourite animals
> /Favourite Animals/,/!/d' data
There's material
at the start of the file
then the key information:
Replacement material
for the favourite animals
and material at the end of the file too.
$
Run Code Online (Sandbox Code Playgroud)

注意:

  • c -您更改整个范围
  • i —在删除整个范围之前,先在范围中的第一个模式之前插入
  • a -您在范围的最后一个模式之后追加,然后删除整个范围

不过,考虑一下,您可以在删除整个范围之前在范围的最后一个模式之前插入,或在删除整个范围之前在范围的第一个模式之后添加。因此,用钥匙ia之前的范围内,基于删除把“替换文本”操作。但是c最简洁。