【问题标题】:sed or awk command to remove lines before first occurrence of a word above a symbolsed 或 awk 命令在符号上方第一次出现单词之前删除行
【发布时间】:2022-01-27 17:09:22
【问题描述】:

原始文件:要查找的单词->“请查找”。符号 -> “在此之上”

some unimportant text
Findme please
some unimportant text
Findme please
some unimportant text
Findme please
Important text
AboveThis
Important text
Findme please

修改文件:

Findme please
Important text
AboveThis
Important text
Findme please

我需要命令搜索符号“AboveThis”上方第一次出现的“请找我”,然后删除上面的所有行。

我试过这个awk -i inplace '/Findme please/{i++}i' file,它会删除行,直到单词第一次出现。

【问题讨论】:

    标签: awk sed scripting


    【解决方案1】:

    我会利用 GNU AWK 来完成这项任务,让 file.txt 内容成为

    some unimportant text
    Findme please
    some unimportant text
    Findme please
    some unimportant text
    Findme please
    Important text
    AboveThis
    Important text
    Findme please
    

    然后

    awk 'BEGIN{RS="Findme please";ORS="Findme please";print ""}/AboveThis/,0{print}' file.txt
    

    输出

    Findme please
    Important text
    AboveThis
    Important text
    Findme please
    

    解释:我通知 GNU AWK 行分隔符 (RS) 是 Findme please,输出行分隔符 (ORS) 是 Findme please。然后我打印空字符串,所以输出以Findme please 开头,然后我提供匹配AboveThis 作为起始条件和0 作为结束条件的行。后者永远不会成立,因此从包含AboveThis 的行开始的所有内容都将是printed。 免责声明:仅使用您提供的示例对解决方案进行了测试。如果您想了解更多关于RSORS 的信息,请阅读8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

    (在 gawk 4.2.1 中测试)

    【讨论】:

    • 感谢您的回复。该命令仅适用于输出到终端。如果我给 awk -i inplace 修改文件,它不会按预期工作。现在,我正在使用“>”选项生成新文件。一旦我检查了正确的 GB 文件,我将标记为已接受的答案。
    • @Daweo Super,谢谢。你是对的,这正在使用这个例子。如果在示例中添加了一些行,则会打印出来,而 OP 想要由 Findme please 围绕 AboveThis 分隔的行块
    • @Jayjargot 我假设 删除上面的所有行意味着只需要删除之前的行,而不是之后
    • @Daweo 你是对的,这就是我想要的(删除上面的所有行),而不是围绕定界。
    【解决方案2】:

    基于状态机的解决方案怎么样:

    awk -i inplace '
    f==1 {buf = buf RS $0}                  # state 1: the word is found
    f==2 {print; next}                      # state 2: the symbol is found
    /AboveThis/ {print buf; buf = ""; f=2}  # flush buf and move to state 2
    /Findme please/ {buf = $0; f=1}         # refresh buf and move to or keep state 1
    ' file
    

    【讨论】:

      【解决方案3】:

      其他解决方案:
      sed中使用贪婪的.*

      sed -Ez 's/.*(Findme please.*Important text)/\1/' file
      

      从文件末尾开始

      tac file | awk '/Findme please/ {if (above) {print; exit} } /Important text/ {above=1} 1' | tac
      

      两次解析文件

      awk '
        NR==FNR && /Findme please/ && important==0 { start=FNR;next}
        /Important text/ {important=1}
        NR!=FNR && FNR>=start {print}
        ' file file
      

      【讨论】:

        【解决方案4】:
        $ tac file | awk '{print} /AboveThis/{f=1} f && /Findme please/{exit}' | tac
        Findme please
        Important text
        AboveThis
        Important text
        Findme please
        

        【讨论】:

          【解决方案5】:

          纯粹的sed 解决方案可能是:

          sed '/Findme please/,$!d
               /AboveThis/!{
                   /Findme please/{h;d;}
                   H;d
               }
               x;G
               :a
               n;ba' file
          

          【讨论】:

            猜你喜欢
            • 2015-06-04
            • 1970-01-01
            • 2013-11-15
            • 2016-01-04
            • 2015-12-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多