【问题标题】:How to properly find and replace a multiline text using sed or awk?如何使用 sed 或 awk 正确查找和替换多行文本?
【发布时间】:2020-04-25 07:11:15
【问题描述】:

尝试替换以下文本时,我收到错误:

sed -i "s/  type pulse
  fallback "sysdefault"
  hint {
    show on
    description "Default ALSA Output (currently PulseAudio Sound Server)"
  }/  type plug
      slave.pcm hw/g" .asoundrc

未找到匹配项:(当前为 PulseAudio 声音服务器)\n }/ 类型 插头\n slave.pcm hw/g

我已经尝试使用 \ 转义 " 或将它们交换为 ' 但错误是:

sed: -e expression #1, char 14: unterminated `s' command

问题与空白/新行有关吗?使用 sed、awk 或 perl 最简单的方法是什么?非常感谢!

【问题讨论】:

    标签: shell sed


    【解决方案1】:

    sed 中的命令由换行符分隔。要匹配多行字符串,您可以使用N 命令读取模式空间中的多行,然后使用\n 正则表达式匹配它们以匹配换行符。如果未找到匹配项,则必须使用保留空间进行洗牌:保留模式空间,打印所有内容直到换行符,使用保留空间切换模式,从模式中删除所有内容直到第一个换行符,阅读下一行,重复。

    这将是一些事情:

    sed '
      : restart
      N;N;N;N;N; # read six lines, we need that many
      : loop
          # match six lines
          /  type pulse\n  fallback "sysdefault"\n  hint {\n    show on\n    description "Default ALSA Output (currently PulseAudio Sound Server)"\n  }/{
               # replace them
               s//    type plug\n      slave.pcm hw/
               # print and start over
               n ; b restart
           }
           # hold, print leading line, change, remove leading line
           h ; s/\n.*// ; p ; x ; s/[^\n]*\n//
           # append next line and loop
           N
      b loop
    '
    

    由于编写这样的脚本很难(对大多数人来说;),有些人只使用 GNU sed -z 选项:

    sed -z 's/  type pulse\n  fallback "sysdefault"\n  hint {\n    show on\n    description "Default ALSA Output (currently PulseAudio Sound Server)"\n  }/  type plug\n      slave.pcm hw/g'
    

    请注意,我认为在 s 命令内的替换字符串中使用 \n 无论如何都是 GNU 扩展。

    【讨论】:

    • 哇,这个大例子太棒了!您推荐哪些资源来学习 sed 和 awk?非常感谢您的详细解释和两个答案!
    • sed introduction by Bruce Barnett 仍然是谷歌中第一个出来的并且很棒。有一天,它只是让我“点击”了什么是模式和保持空间——在理解了这一点之后,它只是脚本。 grymoire.com也有awk介绍。
    【解决方案2】:

    在多行模式下使用

    perl -i -0 -pe '
        s/type pulse.*PulseAudio Sound Server\)/  type plug\n    slave.pcm hw/s
    ' file
    

     输出

    type plug
    slave.pcm hw
    

    注意

    你真正想要达到什么目的?也许有更好的方法。

    【讨论】:

    • 非常有趣!我的输入返回了一个多余的 " 和 } 。即使使用 \,我也无法删除 },尝试了带和不带空格但它不起作用... perl -i -0 -pe 's/type pulse.* PulseAudio Sound Server)\"/ type plug\n slave.pcm hw/s ' [关于注释]我正在尝试自动化音频文件编辑,但是由于我不知道在linux上是否有差异只有当我找到这个确切的块代码时,我才需要更改发行版。感谢您的代码!
    【解决方案3】:

    正如其他人评论的那样,sed 逐行处理文件并且无法处理 多行作为默认行为。一个可能的解决方法是啜饮 在第一阶段使用N 命令的模式空间中的所有行 并在下一步中执行替换。那么怎么样:

    sed '
    :l
    N
    $!b l
    s/ *type pulse\n *fallback "sysdefault"\n *hint {\n *show on\n *description "Default ALSA Output (currently PulseAudio Sound Server)"\n *}/  type plug\'$'\n''  slave.pcm hw/g' .asoundrc
    

    如果文件过大,吞食所有文件可能效率低下 但现在大多数情况下都没有问题。

    【讨论】:

      猜你喜欢
      • 2017-11-11
      • 2014-12-04
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 2020-02-03
      • 1970-01-01
      • 2018-07-02
      • 2010-12-07
      相关资源
      最近更新 更多