仅当模式包含Pattern时,模式的Sed范围

时间:2015-02-25 11:17:54

标签: sed range

我想知道的是如何打印一系列模式,但仅限于它包含特定模式。

例如:

我有一个包含以下内容的文件:

       HEADER 1
  AAA
  BBBBBBB
  MSG:testing
  CCCCCC
  DDD
      PAGE 1

   HEADER 2
EEE
FFFFFF
GGG
HHH
   PAGE 2

我想从任何HEADER打印到任何PAGE,但前提是它包含模式MSG

我想要的结果是只打印这些部分:

      HEADER 1
  AAA
  BBBBBBB
  MSG:testing
  CCCCCC
  DDD
      PAGE 1

到目前为止我所拥有的是:sed -n -e '/HEADER /,/PAGE /p' inputfile.txt > outputfile.txt

我愿意接受任何建议,包括使用Awk或Grep。

提前致谢。

4 个答案:

答案 0 :(得分:1)

sed '/HEADER/ { :a N; /PAGE/!ba; /MSG/!d }' inputfile.txt

的工作原理如下:

/HEADER/ {        # in a line that contains HEADER
  :a              # jump label for looping
  N               # fetch next line, append to pattern space
  /PAGE/!ba       # if the pattern space doesn't contain PAGE (this
                  # is the case if the new line doesn't), go back to :a

  /MSG/!d         # if the block that's now in the pattern space doesn't
                  # contain MSG, discard it
}

这会从文件中删除有问题的范围,并保留其他所有内容。要仅打印匹配范围并丢弃范围之间的垃圾数据,

sed -n '/^HEADER/ { :a N; /PAGE/!ba; /MSG/p }' inputfile.txt

这将删除-n的默认打印操作,并使用/MSG/p显式打印匹配的范围,而不是删除不匹配的范围。

答案 1 :(得分:0)

如果您的日期以空格分隔,则可以使用此gnu awk

awk -v RS= '/MSG/' file
HEADER 1
AAA
BBBBBBB
MSG:testing
CCCCCC
DDD
PAGE 1

通过将RS设置为空,awk在块模式下工作,然后只需选择正确的块。


这使用HEADER作为分隔符。

awk -v RS="HEADER" '/MSG/ {print RS$0}' file
HEADER 1
AAA
BBBBBBB
MSG:testing
CCCCCC
DDD
PAGE 1

答案 2 :(得分:0)

sed -n '/^HEADER/,/^PAGE /!d;H;/^HEADER/h;/^PAGE / {x; /\nMSG/ p;}' YourFile

假设只有且始终以HEADER开头并以PAGE(在不同的行上)结束

阐释:

  • 除非要求打印,否则不要打印输出
  • 如果行不在(包括)HEADERPAGE之间,请将其删除
  • 将行附加到保留缓冲区
  • 如果行为HEADER,则将其写入保留缓冲区(覆盖)
  • 如果行是PAGE
    • 将保持缓冲区加载到工作缓冲区
    • 如果MSG在里面打印
  • 周期

答案 3 :(得分:0)

这可能适合你(GNU sed):

sed '/HEADER/!{H;$!d};x;/MSG/!d' file

如果该行不包含HEADER,则将其附加到保留空间,如果不是最后一行,则将其删除。这意味着任何其他行(包含HEADER或最后一行的行)将与保留空间交换,如果模式空间(多行以前保留空间)不包含MSG,则将其删除。将打印包含MSG的行。