首页 文章

使用sed搜索并替换多行模式

提问于
浏览
2

我已经看过很多关于这个问题的例子,但还没有看到为我量身定做的那个 . 虽然我对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
!

如你所见,我现在不再是猴子的粉丝了 .

2 回答

  • 1

    有多种选择 - 可以使用 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.
    

    所有这三个 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/ 并且不要键入重复的尾随上下文 /!/ . 如果 ia 使用 /!/ 而不是 /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 - 在删除整个范围之前,在范围中的最后一个模式之后追加

    但是,考虑到它,您可以在删除整个范围之前插入范围中的最后一个模式之前,或者在删除整个范围之前追加范围中的第一个模式之后 . 因此, ia 的键是在基于范围的删除之前放置'replacement text'操作 . 但是 c 是最简洁的 .

  • 5

    i (插入)命令具有丑陋的语法,但它的工作原理如下:

    sed '/Favorite Animals/i\
    some new text\
    some more new text\
    and a little more
    /Favorite Animals/,/!/d'
    

相关问题