【问题标题】:multiline pattern delete with single line command使用单行命令删除多行模式
【发布时间】:2013-11-25 03:22:59
【问题描述】:

我想删除我文件中的所有空白段

空段可以由一对以START 开头并以END 结尾的连续行指定。有效段将在以 START 开头和以 END 结尾的行之间包含一些内容

示例输入

Header

START arguments
END

Any contents

START arguments
...
something
...
END

Footer

期望的输出

Header


Any contents

START arguments
...
something
...
END

Footer

在这里我正在寻找可能的一个衬垫。任何帮助将不胜感激。

试验

我尝试关注awk。它在某种程度上有效,但即使在有效段中也会删除 START 行。

awk '/^START/ && getline && /^END$/ {next} 1' file

【问题讨论】:

  • 这会删除 START 行,因为您没有在 getline 之前打印它们。
  • @EtanReisner 我明白这一点,但如果我只打印所有 START 行,那么即使是空段中的行也会被打印。可能我需要更多的调理。还是我错过了什么?
  • 你需要更多的条件,然后你才能得到我相信的模式语句。请参阅我的答案以了解可能性。

标签: perl sed awk grep


【解决方案1】:
perl -00 -pe 's/START .*?\nEND//g' file

这是一个更好的。 如果它们没有被空行分隔,我之前给出的解决方案将丢弃整个段落。

下面的较早回复:

这个 perl one liner 怎么样?

perl -00 -ne 'print if not /START .*\nEND/' file

以段落模式读入文件并丢弃匹配START <string><newline>END的行

【讨论】:

  • 只需将其替换为模式 .* 如果是这样。 perl -00 -ne 'print if not /START .*\nEND/' file
  • 如果您也需要点 . 来匹配换行符,请添加 /s。例如,要删除组织日志抽屉:perl -00 -pe 's/:LOGBOOK:.*?:END://sgi' file.org
【解决方案2】:

在人们提出好的解决方案的同时,我想出了使用sed的替代解决方案

sed '/^START/N;/^START.*END$/d' file

或者按照 @jthill

的建议
sed '/^START/N; /\nEND$/d' file

【讨论】:

  • sed '/^START/N; /\nEND$/d' 需要在第二个模式上使用\n 否则你会在以END 结尾的身体线条上绊倒。
  • @jthill 感谢您的建议。效果很好。添加到ans。我的命令无法重现您的问题,可能是我的文件中没有这种情况。
【解决方案3】:

仅限

awk -v RS='START[^\n]*\nEND\n' '{printf "%s", $0}' file.txt

【讨论】:

  • 哇!不一样的想法,喜欢! '{printf "%s", $0}' 可以简单地是 '1',它会很短
  • @jkshah,使用 1 而不是 {printf "%s", $0} 引入了多余的换行符,但是你可能会再次这样做!
  • +1 你不需要转义 RS 中的反斜杠,但它会被 awk 视为常量 RE 而不是字符串。
【解决方案4】:

也许以下内容会有所帮助:

perl -ne 'print /^START/?do{$x=<>;$_,$x if $x!~/^END/}:$_' inFile

数据集上的输出:

Header


Any contents

START arguments
...
something
...
END

Footer

【讨论】:

    【解决方案5】:
    $ awk '{rec = rec $0 RS} END{ gsub(/START[^\n]*\nEND\n/,"",rec); printf "%s", rec }' file
    Header
    
    
    Any contents
    
    START arguments
    ...
    something
    ...
    END
    
    Footer
    

    【讨论】:

      【解决方案6】:
      /^START/ {
          startline=$0
      
          next
      }
      
      /^END$/ && startline {
          startline=""
          next
      }
      
      startline {
          print startline
      }
      
      startline=""
      
      1
      

      【讨论】:

      • +1。在样本数据上效果很好。但会在没有对的任何孤立 START 或 END 行上失败。
      • 在这些情况下应该采取什么行为?我的答案将包括孤立的 START 行(以及它们之后的所有内容),并且会删除孤立的 END 行(但没有别的)我相信。如果我想它们是倍数,行为会变得更加复杂。
      • 那些案例不应该被删除。
      • 不要为此使用 getline,它引入了大量的包袱和警告,没有明显的好处。请参阅 awk.info/?tip/getline。
      • 在这种情况下,就我所见,next 做了同样的工作,所以这很简单。虽然我不知道我所做的所有警告,但总的来说,请避免使用 getline。
      猜你喜欢
      • 1970-01-01
      • 2012-01-29
      • 2019-06-01
      • 1970-01-01
      • 2020-04-14
      • 2013-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多