回答:
使用できます grep 'string1' filename | grep 'string2'
または、 grep 'string1.*string2\|string2.*string1' filename
grep -e "string1" -e "string2"
これはあなたが探していたものだと思います:
grep -E "string1|string2" filename
私はそれがこのように答えると思います:
grep 'string1.*string2\|string2.*string1' filename
両方が存在する場合にのみ一致し、どちらか一方または両方は一致しません。
grep -e "string1" -e "string2" filename
同じことをしませんか?
How do I match lines that contains *both* strings?
すべての単語を含むファイルを任意の順序で検索するには、次の手順を実行します。
grep -ril \'action\' | xargs grep -il \'model\' | xargs grep -il \'view_type\'
最初のgrepは、再帰検索(r
)を開始します。大文字と小文字を区別せず(i
)、ファイル内の任意の場所にあるl
1つの用語('action'
一重引用符で)に一致する()ファイルの名前をリスト(出力)します。
後続のgrepsは他の用語を検索し、大文字と小文字を区別せずに一致するファイルをリストします。
取得されるファイルの最終的なリストは、これらの用語を含むファイルで、ファイル内の任意の場所に任意の順序で表示されます。
grep -ril 'foo' | xargs -d '\n' grep -il 'bar'
あなたが持っている場合grep
に-P
限られたためのオプションperl
の正規表現は、使用することができます
grep -P '(?=.*string1)(?=.*string2)'
これには、重複する文字列を処理するという利点があります。andロジックをより直接指定できるため、perl
as を使用する方が多少簡単grep
です。
perl -ne 'print if /string1/ && /string2/'
あなたの方法はほぼ良好で、-wが欠けているだけです
grep -w 'string1\|string2' filename
grep -V
が何であるか知りたいです。
grep -w 'regexp1\|regexp2' filename
これにはgrepを使用しないでください。代わりにawkを使用してください。grepで2つの正規表現R1とR2を一致させるには、次のようになります。
grep 'R1.*R2|R2.*R1'
awk中は次のようになります。
awk '/R1/ && /R2/'
しかし、R2
と重複する場合、またはサブセットである場合はR1
どうなりますか?そのgrepコマンドは単にawkコマンドが機能する一方で機能しません。the
and を含む行を検索するとしますheat
。
$ echo 'theatre' | grep 'the.*heat|heat.*the'
$ echo 'theatre' | awk '/the/ && /heat/'
theatre
そのためには、2つのgrepsと1つのパイプを使用する必要があります。
$ echo 'theatre' | grep 'the' | grep 'heat'
theatre
もちろん、実際にそれらを分離する必要があった場合は、常にgrepで使用したものと同じ正規表現をawkに書き込むことができます。可能なすべてのシーケンスで正規表現を繰り返すことを含まない代替のawkソリューションがあります。
それはさておき、3つの正規表現R1、R2、およびR3に一致するようにソリューションを拡張したい場合はどうでしょうか。grepでは、これはこれらの悪い選択の1つになります。
grep 'R1.*R2.*R3|R1.*R3.*R2|R2.*R1.*R3|R2.*R3.*R1|R3.*R1.*R2|R3.*R2.*R1' file
grep R1 file | grep R2 | grep R3
awkでは、簡潔で、明白で、単純で、効率的です。
awk '/R1/ && /R2/ && /R3/'
では、正規表現R1とR2の代わりにリテラル文字列S1とS2を実際に一致させたい場合はどうでしょうか。grepを1回呼び出すだけではこれを実行できません。grepを呼び出す前に、すべてのREメタ文字をエスケープするコードを記述する必要があります。
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
または再度2つのgrepsとパイプを使用します。
grep -F 'S1' file | grep -F 'S2'
これも選択肢としては不十分ですが、awkでは正規表現演算子の代わりに文字列演算子を使用するだけです。
awk 'index($0,S1) && index($0.S2)'
では、段落ではなく行ではなく2つの正規表現を一致させたい場合はどうでしょうか。grepではできません。awkでは簡単です。
awk -v RS='' '/R1/ && /R2/'
ファイル全体でどうですか?繰り返しになりますが、grepおよびawkのささいなことでは実行できません(今回は、簡潔にするために複数文字のRSにGNU awkを使用していますが、awkのコードはそれほど多くありません。 RSが同じことをするための入力に含まれる):
awk -v RS='^$' '/R1/ && /R2/'
したがって、行、段落、またはファイルで複数の正規表現または文字列を検索する場合は、grepを使用せずに、awkを使用してください。
awk '/R1/ && /R2/'
大文字と小文字を区別しませんか?
awk -v IGNORECASE=1 '/R1/ && /R2/'
と他のawk で大文字と小文字を区別しないようにするにはawk '{x=toupper($0)} x~/R1/ && x~/R2/'
git grep
git grep
複数のパターンで使用する構文は次のとおりです。
git grep --all-match --no-index -l -e string1 -e string2 -e string3 file
パターンをや、などのブール式と組み合わせることもできます。--and
--or
--not
man git-grep
ヘルプを確認してください。
--all-match
複数のパターン式を指定する場合、このフラグを指定して、すべてに一致する行があるファイルへの一致を制限します。
--no-index
Gitによって管理されていない現在のディレクトリ内のファイルを検索します。
-l
/--files-with-matches
/--name-only
ファイルの名前のみを表示します。
-e
次のパラメーターはパターンです。デフォルトでは、基本的な正規表現を使用します。
考慮すべきその他のパラメータ:
--threads
使用するgrepワーカースレッドの数。
-q
/--quiet
/--silent
一致した行を出力しません。一致する場合、ステータス0で終了します。
パターンの種類を変更するには、あなたも使用することができます-G
/ --basic-regexp
(デフォルト)、-F
/ --fixed-strings
、-E
/ --extended-regexp
、-P
/ --perl-regexp
、-f file
、およびその他。
関連:
OR演算については、以下を参照してください。
私はよくあなたと同じ問題に出くわします、そして私はスクリプトの一部を書いただけです:
function m() { # m means 'multi pattern grep'
function _usage() {
echo "usage: COMMAND [-inH] -p<pattern1> -p<pattern2> <filename>"
echo "-i : ignore case"
echo "-n : show line number"
echo "-H : show filename"
echo "-h : show header"
echo "-p : specify pattern"
}
declare -a patterns
# it is important to declare OPTIND as local
local ignorecase_flag filename linum header_flag colon result OPTIND
while getopts "iHhnp:" opt; do
case $opt in
i)
ignorecase_flag=true ;;
H)
filename="FILENAME," ;;
n)
linum="NR," ;;
p)
patterns+=( "$OPTARG" ) ;;
h)
header_flag=true ;;
\?)
_usage
return ;;
esac
done
if [[ -n $filename || -n $linum ]]; then
colon="\":\","
fi
shift $(( $OPTIND - 1 ))
if [[ $ignorecase_flag == true ]]; then
for s in "${patterns[@]}"; do
result+=" && s~/${s,,}/"
done
result=${result# && }
result="{s=tolower(\$0)} $result"
else
for s in "${patterns[@]}"; do
result="$result && /$s/"
done
result=${result# && }
fi
result+=" { print "$filename$linum$colon"\$0 }"
if [[ ! -t 0 ]]; then # pipe case
cat - | awk "${result}"
else
for f in "$@"; do
[[ $header_flag == true ]] && echo "########## $f ##########"
awk "${result}" $f
done
fi
}
使用法:
echo "a b c" | m -p A
echo "a b c" | m -i -p A # a b c
必要に応じて、.bashrcに配置できます。
両方の文字列が連続している場合は、grep
コマンドの間にパターンを配置します。
$ grep -E "string1(?.*)string2" file
次の行がというファイルに含まれている場合の例Dockerfile
:
FROM python:3.8 as build-python
FROM python:3.8-slim
文字列を含む行を取得するには、次のFROM python
とas build-python
、次に使用します。
$ grep -E "FROM python:(?.*) as build-python" Dockerfile
次に、出力には両方の文字列を含む行のみが表示されます。
FROM python:3.8 as build-python
ripgrep
以下は使用例rg
です。
rg -N '(?P<p1>.*string1.*)(?P<p2>.*string2.*)' file.txt
Rustの正規表現エンジンの上に構築されているため、最速のgreppingツールの1つです。有限オートマトン、SIMD、および積極的なリテラル最適化を使用して検索を非常に高速にするです。
特に、大きなデータを扱う場合に使用してください。
GH-875の関連機能リクエストも参照してください。
string2
がの前に表示される場合は、これを処理しませんstring1
。この問題の最も簡単な解決策はrg string1 file.txt | rg string2
です。