我已经看到很多关于这个问题的例子,但还没有看到为我量身定制的那个。虽然我对sed非常熟悉,但是当谈到更高级的功能时,我很惭愧地说我是个菜鸟。这是手头的问题。
我有一个多线模式,我可以成功地与sed匹配,
sed -e '/Favorite Animals/, /!/p
Favorite Animals
Monkey
Penguin
Cat
!
Favorite Things
Shoe
Dog
Wheel
Moth
!
我个人喜欢这个表达式的是我可以将可变数量的行匹配到感叹号。现在让我们说我想进行搜索并替换相同的模式。基本上我想用我选择的任何字符串替换之前演示过的多行模式。有任何想法吗?我希望与我演示的sed命令有类似的语法,但乞丐不能选择。
我的想法是,我可以用字符串替换感叹号分隔的其中一个组。我称之为“条目”。我希望能够更新或覆盖这些条目。如果我有一个最喜欢的动物的更新版本,我希望能够用这样的新条目替换旧条目。
Favorite Animals
Sloth
Platypus
Badger
Dog
!
Favorite Things
Shoe
Dog
Wheel
Moth
!
正如你所看到的,我现在不再是猴子的粉丝了。
答案 0 :(得分:4)
有多种选择 - i
,c
和a
命令都可以使用。
此修订后的答案涉及问题中现在修改的数据文件。这是修改后的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.
这三个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
示例输出:
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.
脚本全部使用唯一字符串/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.
/!/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.
是否可以使用sed选择范围内的范围?基本上,如果我想在之前指定的范围内更改或删除一个/多个我最喜欢的动物,该怎么办?那是
/Favorite Animals/,/!/...
在这个范围内改变的东西。
是的,当然。对于单个映射:
sed '/Favourite Animals/,/!/ s/Monkey/Gorilla/'
对于多个映射:
sed '/Favourite Animals/,/!/ {
s/Monkey/Gorilla/
s/Penguin/Zebra/
s/Cat/Dog/
}'
如果您愿意,也可以将它们组合成一行 - 使用分号分隔它们:
sed '/Favourite Animals/,/!/ { s/Monkey/Gorilla/; s/Penguin/Zebra/; s/Cat/Dog/; }'
请注意,GNU sed
和BSD(Mac OS X)sed
对最后一个分号的必要性有不同的看法 - 显示的内容对两者都有效。
原始答案适用于更简单的输入文件。
考虑包含以下内容的文件data
There's material
at the start of the file
then the key information:
Favourite Animals
Monkey
Penguin
Cat
!
and material at the end of the file too.
使用c
,您可以写:
$ sed '/Favourite Animals/,/!/c\
> Replacement material\
> for the favourite animals
> ' 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.
$
使用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.
$
使用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.
$
请注意:
c
- 您更改了整个范围i
- 在删除整个范围之前插入范围中的第一个模式a
- 在删除整个范围之前追加范围中的最后一个模式但是,考虑到它,您可以在删除整个范围之前插入范围中的最后一个模式之前,或者在删除整个范围之前追加范围中的第一个模式之后。因此,i
和a
的键是在基于范围的删除之前放置“替换文本”操作。但c
最简洁。
答案 1 :(得分:1)
i
(插入)命令具有难看的语法,但它可以工作:
sed '/Favorite Animals/i\
some new text\
some more new text\
and a little more
/Favorite Animals/,/!/d'