私は、「レモン」と「米」という単語を含む行をフィルターする方法を見つけようとしてきました。 「レモン」または「米」を見つける方法は知っていますが、それらの2つは見つけません。それらは他のテキストの隣にある必要はなく、同じテキスト行にある必要があります。
「両方とも同じ行に」とは、「「ライス」の後にランダムな文字が続き、「レモン」が続く、またはその逆」という意味です。
正規表現では、rice.*lemon
またはlemon.*rice
です。 |
を使用してそれを組み合わせることができます:
grep -E 'rice.*lemon|lemon.*rice' some_file
拡張正規表現(-E
)ではなく通常の正規表現を使用する場合は、|
の前にバックスラッシュが必要です。
grep 'rice.*lemon\|lemon.*rice' some_file
すぐに少し長くなり、通常はgrep
の複数の呼び出しを使用する方が簡単な、より多くの単語については、たとえば:
grep rice some_file | grep lemon | grep chicken
最初のgrepコマンドの出力を別のgrepコマンドにパイプすると、両方のパターンに一致します。そのため、次のようなことができます。
grep <first_pattern> <file_name> | grep <second_pattern>
または、
cat <file_name> | grep <first_pattern> | grep <second_pattern>
ファイルにコンテンツを追加してみましょう。
$ echo "This line contains lemon." > test_grep.txt
$ echo "This line contains rice." >> test_grep.txt
$ echo "This line contains both lemon and rice." >> test_grep.txt
$ echo "This line doesn't contain any of them." >> test_grep.txt
$ echo "This line also contains both rice and lemon." >> test_grep.txt
ファイルに含まれるもの:
$ cat test_grep.txt
This line contains lemon.
This line contains rice.
This line contains both lemon and rice.
This line doesn't contain any of them.
This line also contains both rice and lemon.
それでは、必要なものをgrepしましょう。
$ grep rice test_grep.txt | grep lemon
This line contains both lemon and rice.
This line also contains both rice and lemon.
両方のパターンが一致する行のみを取得します。これを拡張し、出力を別のgrepコマンドにパイプして、さらに「AND」一致を検索できます。
質問は「grep」を要求しますが、単純な「awk」ソリューションを投稿すると役立つと思いました。
awk '/lemon/ && /rice/'
これは、より多くの単語、または「and」以外のブール式で簡単に拡張できます。
grep with -P
(Perl-Compatibility) オプションおよび positive lookahead regex (?=(regex))
:
grep -P '(?=.*?lemon)(?=.*?rice)' infile
or代わりに以下を使用できます:
grep -P '(?=.*?rice)(?=.*?lemon)' infile
.*?
は、パターンが続くオプションの(rice
またはlemon
)に0回以上.
出現する任意の文字*
と一致することを意味します。 ?
は、その前のすべてをオプションにします(一致するすべての.*
の0回または1回を意味します)(?=pattern)
:ポジティブルックアヘッド:ポジティブルックアヘッドコンストラクトは、括弧のペアで、開始括弧の後に疑問符と等号が続きます。
したがって、これはlemon
とrice
の両方をランダムな順序で含むすべての行を返します。また、これは|
sと2倍のgrep
sの使用を回避します。
grep -e foo -e goo
Fooまたはgooのいずれかの一致を返します
grep
に基づく上記の回答のように、awk
に基づいていない回答を提供することが認められる場合、次のような単純なPerl
行を提案します。
$ Perl -ne 'print if /lemon/ and /rice/' my_text_file
検索では、/lemon/i and /rice/i
のような一部またはすべての単語の大文字小文字を無視することができます。ほとんどのUnix/Linuxマシンでは、とにかくPerlがインストールされています。
Grepパイピングソリューションを自動化するスクリプトを次に示します。
#!/bin/bash
# Use filename if provided as environment variable, or "foo" as default
filename=${filename-foo}
grepand () {
# disable Word splitting and globbing
IFS=
set -f
if [[ -n $1 ]]
then
grep -i "$1" ${filename} | filename="" grepand "${@:2}"
else
# If there are no arguments, assume last command in pipe and print everything
cat
fi
}
grepand "$@"