GREP / SED 或 AWK:根据模式匹配打印文件中的整个段落

GREP / SED 或 AWK:根据模式匹配打印文件中的整个段落

我有一个包含数百个段落的文件,每个段落大约 15 行。我需要寻找一种模式,比如说发生次数:1。如果在段落中找到这种模式,我需要打印整个段落。请注意,段落之间由 2 个换行符分隔。

我已经尝试了下面的代码行,这显然打印了文件中的第一个匹配项。我不知何故无法使用循环并打印所有此类事件。

sed -n '1,/Occurrence: 1/p' ystdef.txt | tail -9 > ystalarm.txt

我可以使用g(全局)标志来sed完成这项工作吗?如果是,怎么办?

请注意,我知道这些grep -A/B/C命令,但它们无法在我的 Cygwin 终端上运行。

答案1

您可以使用 awk 的“段落模式”,其中输入记录由至少两个换行符的序列分隔。这是通过设置RS为空字符串来激活的。

awk -v RS= '/Occurance: 1/' ystdef.txt

请注意,这些段落将全部折叠在一起打印(其内容之间有一个换行符)。 awk 不允许您将输出分隔符与输入分隔符相匹配(某些 GNU awk 扩展除外),但您可以轻松地将段落分隔符标准化为两个换行符。

awk -v RS= -v ORS='\n\n' '/Occurance: 1/' ystdef.txt

如果您不想在末尾添加额外的换行符:

awk -v RS= '/Occurance: 1/ {if (not_first) print ""; print; not_first=1}' ystdef.txt

答案2

这是 GNU 中的sed

sed '/./{H;$!d};x;/SEARCH/!d'

可移植/POSIX 语法:

sed -e '/./{H;$!d;}' -e 'x;/SEARCH/!d'

如果一行包含一个或多个字符,则会将其附加到H旧空格中;如果是!最后$一行,则将其删除。这意味着每一个非空白行都会被存储并从输出中删除。

所以如果一条线是不是 deleted 然后sedex更改保持和模式空间的内容。这使得保留空间只有一个空行,并且模式空间自最后一个空行以来的所有行。

sed然后解决模式/SEARCH/。如果!没有找到,它将 d删除模式空间而不打印,否则默认打印该段落。

这是一个 shell 函数,以您的问题作为输入:

注意 - 为了便于阅读,在本网站的代码突出显示时,对处理后的数据进行了注释。它将按原样工作或没有哈希值。

_pgraph() { 
    sed '/./{H;$!d};x;/'"$1"'/!d'
} <<\DATA
#    I have a file with hundreds of paragraphs of
#    around 15 lines each. I need to search for a
#    pattern, say Occurance: 1. If this pattern is
#    found in the para, I need to print the entire
#    paragraph. Note that the paragraps are seperared
#    by 2 new line characters.

#    I have tried the below line of code and this
#    obviously prints the first occurence in the
#    file. I am somehow unable to use a loop and
#    print all such occurances.

#    sed -n '1,/Occurance: 1/p' ystdef.txt | tail -9 >
#    ystalarm.txt Can I use the g (global) flag with
#    sed to make this work? If yes, how?

#    Note that I am aware of the grep -A/B/C commands
#    but they wont work on my cygwin terminal.
DATA

现在我可以做:

_pgraph Note

###OUTPUT

#    I have a file with hundreds of paragraphs of
#    around 15 lines each. I need to search for a
#    pattern, say Occurance: 1. If this pattern is
#    found in the para, I need to print the entire
#    paragraph. Note that the paragraps are seperared
#    by 2 new line characters.

#    Note that I am aware of the grep -A/B/C commands
#    but they wont work on my cygwin terminal.

或者更具体地说:

_pgraph 'Note that I'

#    Note that I am aware of the grep -A/B/C commands
#    but they wont work on my cygwin terminal.

您可以对任何文件执行相同的操作,而无需将文字输入附加到函数本身,只需删除函数定义中的所有内容并运行它,如下所示<<\DATADATA

_pgraph 'PATTERN' </path/to/input.file

答案3

您可以在 Perl 中使用“段落模式”:

perl -ne 'BEGIN{ $/ = "" } print if /pattern/' input

相关内容