查找包含单词列表的段落

查找包含单词列表的段落

我在名为pattern.txt 的文件中有一个单词列表。我需要搜索包含列表中所有单词的输入流的段落。对于段落中的单个单词 (foo),我通常使用 sed 代码:

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

但我不知道如何对单词列表执行此操作。

答案1

使用 GNU awk:

$ cat patterns.txt
foo
bar
baz
$ cat file
first paragraph foo bar

second baz bar foo

third

fourth foo baz bar

fifth baz foo

这里cat file代表输入流:

$ cat file | gawk '
    NR == FNR {pattern[++n] = $0; next}
    ENDFILE {RS = ""; ORS = "\n\n"}
    {for (i = 1; i <= n; i++) if ($0 !~ pattern[i]) next; print}
' patterns.txt -   # note the trailing hyphen
second baz bar foo

fourth foo baz bar

RS = ""更改 awk 以将空行分隔的段落读取为记录。

答案2

perl

perl -ne '
  BEGIN {chomp(@patterns = <STDIN>); $/ = ""}
  for $p (@patterns) {next LINE unless /$p/}
  print' -- your-file < patterns.txt

请注意,模式被解释为 perl 正则表达式,而不是像 in 那样的基本正则表达式sed或像 in 那样的扩展正则表达式awk。它们大多与扩展正则表达式向后兼容。

但请注意,默认情况下.不会匹配换行符。您可以添加s标志(/$p/s而不是/$p/)来更改它。

除此之外,如果他们在 工作awk,他们很可能会在 工作perl。它们对 BRE 或 ERE 有很多扩展,其中一些对于段落内匹配非常有用。例如,(?m)^foo$将匹配包含恰好为 的行的段落foo。 perl 正则表达式已成为事实上的标准,其大部分扩展可在大多数现代编程语言中使用,包括 python、php 以及所有使用 PCRE 或 PCRE2 的语言。

答案3

使用(以前称为 Perl_6)

~$ raku -e 'for slurp.split("\n\n") { .put if (/foo/ & /bar/ & /baz/) };'  file

或者

~$ raku -e 'for slurp.split("\n\n") { .put if all(/foo/, /bar/,  /baz/) };'  file

Raku 是 Perl 家族的一种编程语言。上面,文件被slurp编辑(即一次读取所有内容),分成段落\n\n。这些段落元素使用 进行迭代for,并且if存在与适当的正则表达式的匹配项(使用&布尔值运算符),该段落已结束put。第二个代码示例与第一个代码示例类似,但具有 Raku 的新“Junction”运算符all。 Raku 中有四个“Junction”运算符:allanyonenone

注意:如果段落由两个或多个换行符分隔,请split与正则表达式参数一起使用,如.split( / \n ** 2..* / ).


输入示例(感谢@glenn_jackman):

first paragraph foo bar

second baz bar foo

third

fourth foo baz bar

fifth baz foo

示例输出:

second baz bar foo
fourth foo baz bar

以“模式”作为输入文件: 如果您不想写出上面的模式匹配,您可以在上面的代码前面添加一个空格分隔的列表(请参阅底部的第一个链接以了解“单词引用”选项):

~$ raku -e 'my @words = <foo bar baz> ; for slurp.trim.split("\n\n") { .put if .match: all @words };'  file

或者您可以直接从文件中读取“模式”(假设每行一个“模式”,如 @glenn_jackman 的答案):

~$ raku -e 'my @words = "patterns.txt".IO.lines; for slurp.trim.split("\n\n") { .put if .match: all @words };'  file

如果您只想将空格分隔的“单词”用作测试模式输入文件,则上面的输入行可简化为:

my @words = "patterns.txt".IO.words;


https://docs.raku.org/language/quoting
https://docs.raku.org/type/Junction
https://raku.org

相关内容