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
sed
パターンは、inなどの基本正規表現やinなどの拡張正規表現ではなく、perl正規表現として解釈されます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
。 2番目のコード例は最初のコード例と似ていますが、Rakuの新しい「Junction」演算子が含まれていますall
。 Rakuにはall
、、、any
およびone
4つの「Junction」演算子がありますnone
。
注:段落が複数の改行で区切られている場合など、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の答えと同じように、1行に1つの「パターン」と仮定)。
~$ 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/言語/quoting
https://docs.raku.org/type/Junction
https://raku.org