2つの異なる文字列を含む行を一致させるためにgrep
を使用しようとしています。私は以下を試しましたが、これはstring1またはのどちらかを含む行と一致します。 )string2これは私が欲しいものではありません。
grep 'string1\|string2' filename
それでは、両方の文字列を含む行だけをgrep
と照合するにはどうすればよいでしょうか。
あなたはgrep 'string1' filename | grep 'string2'
を使うことができます
または、grep 'string1.*string2\|string2.*string1' filename
私はこれがあなたが探していたものだと思います:
grep -E "string1|string2" filename
私はそのような答えを考えています:
grep 'string1.*string2\|string2.*string1' filename
両方が存在する場合にのみ一致し、一方または他方または両方には一致しません。
複数の-e
オプションを指定するだけです。
-e pattern, --regexp=pattern
Specify a pattern used during the search of the input: an input
line is selected if it matches any of the specified patterns.
This option is most useful when multiple -e options are used to
specify multiple patterns, or when a pattern begins with a dash
(`-').
したがって、コマンドは次のようになります。
grep -e "string1" -e "string2" filename
注:上記でBSD版のマニュアルを引用しましたが、Linuxでも 同じです 。
すべての単語を含むファイルを任意の順序でどこでも検索するには、次の手順を実行します。
grep -ril \'action\' | xargs grep -il \'model\' | xargs grep -il \'view_type\'
最初のgrepは再帰的検索(r
)をキックオフします。大文字と小文字の区別(i
)を無視し、ファイル内の任意の場所('action'
)と一致するファイル名(l
)をリスト(表示)します。
後続のgrepsは他の用語を検索し、大文字と小文字を区別しないで一致するファイルをリストします。
あなたが得ることになるファイルの最終的なリストは、ファイル内の任意の場所でこれらの用語を含むものになります。
限定されたgrep
正規表現に対して-P
オプションを指定したPerl
がある場合は、
grep -P '(?=.*string1)(?=.*string2)'
これには、重複する文字列を扱うという利点があります。 Perl
をgrep
として使用する方がやや簡単です。これはandロジックをより直接的に指定できるからです。
Perl -ne 'print if /string1/ && /string2/'
あなたの方法はほとんど良かった、-wがないだけ
grep -w 'string1\|string2' filename
あなたはこのようなことを試すことができます:
(pattern1.*pattern2|pattern2.*pattern1)
正規表現の|
演算子は、またはを意味します。つまり、string1またはstring2のどちらかが一致します。あなたがすることができます:
grep 'string1' filename | grep 'string2'
これは最初のコマンドの結果を2番目のgrepに送ります。それはあなたに両方にマッチする行だけを与えるべきです。
そして、人々がPerlとpythonを示唆し、そして複雑なシェルスクリプトを提案したように、ここで簡単なawkアプローチ:
awk '/string1/ && /string2/' filename
受け入れられた答えに対するコメントを見たことはありません:いいえ、これは複数行にはなりません。しかし、それは質問の作者が求めたものでもありません。
6個のスペースで始まり、以下で終わる行が見つかりました。
cat my_file.txt | grep
-e '^ .*(\.c$|\.cpp$|\.h$|\.log$|\.out$)' # .c or .cpp or .h or .log or .out
-e '^ .*[0-9]\{5,9\}$' # numers between 5 and 9 digist
> nolog.txt
ファイルtestfileで複数の単語の数を見つける必要があるとしましょう。それに取り組む2つの方法があります
1)正規表現のマッチングパターンでgrepコマンドを使う
grep -c '\<\(DOG\|CAT\)\>' testfile
2)egrepコマンドを使用
egrep -c 'DOG|CAT' testfile
Egrepを使用すると、式を気にする必要はなく、単語をパイプ区切り文字で区切るだけで済みます。
grep ‘string1\|string2’ FILENAME
GNU grepバージョン3.1
grep -i -w 'string1\|string2' filename
これは、単語の完全一致と大文字と小文字を区別しない単語の一致のために機能します。
Grepしたい文字列をファイルに入れる
echo who > find.txt
echo Roger >> find.txt
echo [44][0-9]{9,} >> find.txt
次に-fを使って検索します。
grep -f find.txt BIG_FILE_TO_SEARCH.txt
grep '(string1.*string2 | string2.*string1)' filename
任意の順序でstring1とstring2の行を取得します
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
などを使用することもできます。
関連する
または操作については、以下を参照してください。
複数行一致の場合
echo -e "test1\ntest2\ntest3" |tr -d '\n' |grep "test1.*test3"
または
echo -e "test1\ntest5\ntest3" >tst.txt
cat tst.txt |tr -d '\n' |grep "test1.*test3\|test3.*test1"
改行文字を削除するだけでうまくいきます。
私はよくあなたと同じ問題に出くわします、そして私はただスクリプトの一部を書きました:
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 'string1' file | grep 'string2'
これにはgrepを使わないでください。代わりにawkを使ってください。 grepで2つの正規表現R1とR2を一致させるには、次のようになると思います。
grep 'R1.*R2|R2.*R1'
awkの間にそれはあるだろう:
awk '/R1/ && /R2/'
しかし、R2
がR1
と重なる、またはそのサブセットである場合はどうなりますか。そのgrepコマンドは、awkコマンドでは機能しません。 the
と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を一度呼び出すだけではできません。grepを呼び出す前に、すべてのREメタ文字をエスケープするコードを書く必要があります。
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
または2グレップとパイプをもう一度使用します。
grep -F 'S1' file | grep -F 'S2'
これはやはり悪い選択ですが、awkでは単にregexp演算子の代わりに文字列演算子を使用します。
awk 'index($0,S1) && index($0.S2)'
では、行ではなく段落で2つの正規表現を一致させたい場合はどうしますか。 grepではできない、awkではささいなこと:
awk -v RS='' '/R1/ && /R2/'
ファイル全体ではどうでしょうか。ここでも、awkではgrepでささいなことをすることはできません(今回は簡潔にするためにマルチ文字RSにGNU awkを使用しますが、他のawkではこれ以上コードを使用しません。あなたが知っているcharは、RSが同じことをするための入力には含まれません。
awk -v RS='^$' '/R1/ && /R2/'
そのため、行、段落、またはファイル内で複数の正規表現または文字列を検索する場合は、grepを使用しないでください。awkを使用してください。