Grep 包含特定关键字的文本的整个段落

问题描述 投票:0回答:4

我的目标是提取包含特定关键字的文本段落。不仅仅是包含关键字的行,而是整个段落。我的文本文件的规则是每个段落都以某种模式开头(例如 Pa0),该模式仅在段落开头在整个文本中使用。每个段落都以换行符结尾。

例如,假设我有以下文本:

Pa0 
This is the first paragraph bla bla bla
This is another line in the same paragraph bla bla 
This is a third line bla bla 

Pa0
This is the second paragraph bla bla bla
Second line bla bla My keyword is here!
bla bla bla 
bla 

Pa0
Hey, third paragraph bla bla bla!
bla bla 

Pa0
keyword keyword
keyword
Another line! bla 

我的目标是提取这些包含“关键字”一词的段落。例如:

Pa0
This is the second paragraph bla bla bla
Second line bla bla My keyword is here!
bla bla bla 
bla 

Pa0
keyword keyword
keyword
Another line! bla 

我可以使用例如grep 关键字和 -A、-B 或 -C 选项可获取关键字所在行之前和/或之后的恒定行数,但这似乎还不够,因为文本块的开头和结尾取决于分隔符“Pa0”和“ ”.

任何有关

grep
或其他工具(例如 awk、sed、perl)的建议都会有所帮助。

text awk grep paragraph
4个回答
14
投票

很简单

awk
:

awk '/keyword/' RS="\n\n" ORS="\n\n" input.txt

说明:

通常 awk 以每行为基础进行操作,因为记录分隔符

RS
的默认值是
\n
(单个新行)。通过将
RS
依次更改为两行(空行),我们可以轻松地在段落基础上进行操作。

/keyword/
是一个条件,一个正则表达式。由于条件
awk
之后没有任何操作,如果它包含
keyword
,将简单地打印未更改的记录(段落)。

将输出记录分隔符

ORS
设置为
\n\n
将会用空行分隔输出的段落,就像在输入中一样。


4
投票

如果text.txt包含您想要的文本,则:

$ sed -e '/./{H;$!d;}' -e 'x;/keyword/!d;' text.txt
Pa0
This is the second paragraph bla bla bla
Second line bla bla My keyword is here!
bla bla bla
bla

Pa0
keyword keyword
keyword
Another line! bla

1
投票

希望这会有所帮助

sed -n '/Pa0/,/^$/p' 文件名

cat 文件名 | sed -n '/Pa0/,/^$/p'

-n,抑制图案空间的自动打印

-p,打印当前图案空间

/Pa0/,以 Pa0 模式开始的段落

/^$/,以空行结尾的段落

^,行首

$,行尾

参考: http://www.cyberciti.biz/faq/sed-display-text/


0
投票

只要使用正确的命令行开关,使用 Perl 就可以轻松做到这一点:

perl -wn00e "print if /keyword/" input.txt

开关

-w00ne
可能看起来令人难以承受,所以让我们将其分解并一次检查一个开关。如果这对您来说更容易,可以将上面的命令重新编写,并将开关拆分为:

perl -w -n -00 -e "print if /keyword/" input.txt

这是四个开关:

  • -w:这会打开警告。这里并不是严格需要它,但它不会伤害任何东西,并且可以指出您可能忽略的代码中的错误。只需按一下键盘即可使用,省去了很多麻烦,所以为什么不使用它呢?
  • -n:这使得实际代码(-e开关之后的部分)在输入的每一行(或者更确切地说,记录)上执行。您可以通过运行
    perldoc perlrun
    并搜索
    -n
    开关来了解更多信息。
  • -00:此开关使 -n 在每个段落上执行,而不是在每行上执行默认值。 (基本上,它将记录更改为段落,而不是默认的行。)请注意, switch 是双零,而不是双大写字母 O。
  • -e:如果在 bulk 开关中指定(与其他开关一起),则必须最后使用此开关,因为接下来的程序将在每一行/段落/记录上运行。

每一段执行的程序是:

print if /keyword/

这是一个非常短的程序,仅使用正则表达式来检查

keyword
是否包含在行/段落/记录中,如果找到,则打印该记录。

请注意,您可以在

i
的末尾添加
/keyword/
,使其成为不区分大小写的匹配,如下所示:

print if /keyword/i

事实上,您可以在 Perl 允许的常规

/keyword/
匹配之后放置任何修饰符。

还有一件事:

如果你真的不喜欢把

m/.../

放在

/keyword/
之后(有些人出于某种原因这样做),你可以将程序重写为:
print

但在我看来,
/keyword/ and print

读起来很愉快,因为短语“如果匹配则打印”遵循自然的英语语法。

    

© www.soinside.com 2019 - 2024. All rights reserved.