【问题标题】:Searching a string and replacing another string above the searched string搜索字符串并替换搜索字符串上方的另一个字符串
【发布时间】:2020-01-06 22:26:08
【问题描述】:

我有一个包含以下行的文件

123
456
123
789
abc
efg
xyz

我需要使用abc 进行搜索,并用111 替换正上方的123。这是要求,abc 在文件中仅出现一次,但123 可以多次出现,123 可以在abc 上方的任何位置。 请帮帮我。

我已尝试使用以下 sed 命令

sed -i.bak "/abc/!{x;1!p;d;};x;s/123/1111" filename

使用上面的命令,它只是替换123,如果123刚好在abc之上,如果123abc之上2行,那么替换失败。

【问题讨论】:

    标签: shell awk sed


    【解决方案1】:
    $ tac file | awk 'f && sub(/123/,"111"){f=0} /abc/{f=1} 1' | tac
    123
    456
    111
    789
    abc
    efg
    xyz
    

    【讨论】:

      【解决方案2】:

      这可能对你有用(GNU sed):

      sed -Ez 's/(.*)(\n123.*\nabc)/\1\n111\2/' file
      

      这会将文件吞入内存并在abc 之前的最后一次出现123 之前插入111

      一种占用内存较少的解决方案:

      sed -E '/^123$/{:a;N;/\n123$/{h;s///p;g;s/.*\n//;ba};/\nabc$/!ba;s/^/111\n/}' file
      

      这会收集包含123 的行之后的行。如果遇到包含123 的另一行,它将卸载之前的所有行并再次开始收集行。如果它找到包含abc 的行,它会在到目前为止收集的行的前面插入111

      另一种选择:

      sed '/abc/{x;/./{s/^/111\n/p;z};x;b};/123/{x;/./p;x;h;$!d;b};x;/./{x;H;$!d};x' file 
      

      【讨论】:

        【解决方案3】:

        这是一个经典案例,您可以跟踪上一行并根据满足当前行的条件更改内容。通常,awk 程序如下所示:

        awk '(FNR==1){prev=$0; next}
             (condition_on_$0) { action_on_prev }
             { print prev; prev = $0 }
             END { print $0 }'
        

        所以在 OP 的情况下,这将是:

        awk '(FNR==1){prev=$0; next}
             $0 == "abc" { if (prev == "123") prev = "111" }
             { print prev; prev = $0 }
             END { print $0 }'
        

        【讨论】:

          【解决方案4】:

          ed 可以方便地在脚本中进行复杂的文件编辑:

          ed -s file <<EOF
          /^abc$/;?^123$?;.c
          111
          .
          w
          EOF
          

          This:将当前行设置为匹配abc (/^abc$/;) 的第一行。然后将与123 匹配的第一行before 更改为111?XXX? 向后搜索匹配的正则表达式,?^123$?;.c 选择该单行以 change) 最后保存修改后的文件。

          【讨论】:

            【解决方案5】:

            要做的事情远不止于此。这是一个:

            sed -i.bak '1{h;d;};/123/{x;p;d;};/abc/{x;s/123/111/;p;d;};H;${x;p;};d' filename
            

            【讨论】:

            • 感谢您的帮助,这是可行的,但是当我将变量用于“abc”时,变量替换失败
              var=abc sed -i.bak '1{h;d;}; /123/{x;p;d;};/${var}/{x;s/123/111/;p;d;};H;${x;p;};d' 文件名
            • @kiranpaila:试试sed "...$var..."(注意双引号和没有括号。)
            • 如何使用下面的命令只搜索以上 5 行替换 sed -i.bak '1{h;d;};/123/{x;p;d;};/ abc/{x;s/123/111/;p;d;};H;${x;p;};d' 文件名 只需要检查前几行而不是所有前行
            猜你喜欢
            • 2022-08-17
            • 2017-04-16
            • 2019-03-28
            • 1970-01-01
            • 2021-11-28
            • 2010-11-14
            • 1970-01-01
            相关资源
            最近更新 更多