【问题标题】:Delete a line with a pattern ONLY when the previous line has another specific pattern仅当前一行具有另一个特定模式时才删除具有模式的行
【发布时间】:2021-09-26 20:39:34
【问题描述】:

仅当前一行具有另一种特定模式(PATTERN 1)时,我才尝试删除具有特定模式(PATTERN 2)的所有行。

代码如下所示:

PATTERN 1
PATTERN 2   <- This line should be deleted
NNN
PATTERN 2
PATTERN 1
PATTERN 2   <- This line should be deleted
blabla
PATTERN 1
blabla
PATTERN 2
PATTERN 1
PATTERN 2   <- This line should be deleted

PATTERN 2 仅在上一行为 PATTERN 1

时才应删除
  • 我知道如何使用 PATTERN 2 删除所有行:sed '/PATTERN 2/d'
  • 我可以删除 PATTERN 1 之后的所有行:sed '/PATTERN 1/{n;N;d}'

但是,我不知道将这两个要求应用于单个 AWK 或 SED。

如何用 AWK 做到这一点?提前谢谢你,

【问题讨论】:

  • 在谈论匹配文本时切勿使用“模式”一词,因为它是模棱两可的。请阅读stackoverflow.com/questions/65621325/… 以了解该问题,然后将“模式”替换为字符串或正则表达式,并在您的问题中出现的任何地方全部或部分替换。

标签: awk


【解决方案1】:

假设“PATTERN”是指“部分正则表达式匹配”,因为这是您在问题中的 sed 脚本中使用的内容:

$ awk '!(/PATTERN 2/ && prev~/PATTERN 1/); {prev=$0}' file
PATTERN 1
NNN
PATTERN 2
PATTERN 1
blabla
PATTERN 1
blabla
PATTERN 2
PATTERN 1

【讨论】:

    【解决方案2】:
    Mac_3.2.57$cat input | awk '{if(lastline!="PATTERN 1"||$0!="PATTERN 2"){print}};{lastline=$0}'
    PATTERN 1
    NNN
    PATTERN 2
    PATTERN 1
    blabla
    PATTERN 1
    blabla
    PATTERN 2
    PATTERN 1
    Mac_3.2.57$cat input 
    PATTERN 1
    PATTERN 2
    NNN
    PATTERN 2
    PATTERN 1
    PATTERN 2
    blabla
    PATTERN 1
    blabla
    PATTERN 2
    PATTERN 1
    PATTERN 2
    Mac_3.2.57$
    

    【讨论】:

    • 谢谢!我刚刚尝试过,但它正在打印所有内容(当第一个模式在前一行时,它不会删除第二个模式)。
    • 你可以看到它对我有用,对吧?请发布您的代码、运行和输入。
    • 谢谢安德鲁。我已经在我的 Mac 上完成了测试,它确实可以工作......但它不在 WSL 上。应该是我电脑的问题。我会仔细看看的。 $ cat t.txt | awk '{if(lastline!="PATTERN 1"||$0=!"PATTERN 2"){print}};{lastime=$0}'PATTERN 1 PATTERN 2 NNN PATTERN 2 PATTERN 1 PATTERN 2 blabla PATTERN 1 blabla PATTERN 2 PATTERN 1 PATTERN 2$ cat t.txtPATTERN 1 PATTERN 2 NNN PATTERN 2 PATTERN 1 PATTERN 2 blabla PATTERN 1 blabla PATTERN 2 PATTERN 1 PATTERN 2
    【解决方案3】:

    使用您显示的示例/尝试,请尝试遵循awk 代码。

    awk '/PATTERN 1/{found=1;print;next} found && /PATTERN 2/{found="";next} 1' Input_file
    

    说明:为上述添加详细说明。

    awk '                   ##Starting awk program from here.
    /PATTERN 1/{            ##Checking if line contains PATTERN 1 then do following.
      found=1               ##Setting found to 1 here.
      print                 ##printing current line here.
      next                  ##next will skip all further statements from here.
    }
    found && /PATTERN 2/{   ##Checking condition if found is NOT NULL AND PATTERN 2 is found.
      found=""              ##Nullifying found here.
      next                  ##next will skip all further statements from here.
    }
    1                       ##printing current line here.
    ' Input_file            ##Mentioning Input_file name here.
    

    【讨论】:

    • 非常感谢您的回复和详细的解释!我刚刚做了一个测试,但是删除了一个额外的 PATTERN 2(源代码的第 10 行:ideone.com/d2oZBR)。此行不应删除,因为上一行不是 PATTERN 1。
    • @Pierre,欢迎您,试试awk '/PATTERN 1/{found=1;print;next} found &amp;&amp; ++count==1{if($0~/PATTERN 2/){next};count=found=""} 1' Input_file 一次怎么样?告诉我进展如何?
    【解决方案4】:

    另一个变化可能是检查当前行是否匹配PATTERN 2,最后一行是否匹配PATTERN 1

    如果是这种情况,则打印当前行,否则不打印就移至下一行。

    awk '{if(/PATTERN 2/&&last~/PATTERN 1/){last=$0;next}last=$0}1' file
    

    查看awk demo

    以更易读的格式:

    awk '
    {
      if (/PATTERN 2/ && last ~ /PATTERN 1/) {   # If both patterns match
        last = $0                                # Save the last line, but don't print
        next                                     # Go on to the next record
      }
      last = $0                                  # Save the last line
    }1                                           # Print the line
    ' file
    

    【讨论】:

      猜你喜欢
      • 2013-06-15
      • 1970-01-01
      • 1970-01-01
      • 2019-08-17
      • 2017-10-20
      • 1970-01-01
      • 2015-06-29
      • 2023-01-31
      • 1970-01-01
      相关资源
      最近更新 更多