grepで正確な文字列を見つける


9

例として、私は多くのメールアドレスを含む大きなテキストファイルを持っています。bashを使用して、メールが存在する(または存在しない)ことを検索/確認する必要があります。「アンカー」(のみ)を使用する必要がありますか?

grep '^user1@example.com' text_file

またはより良い方法がありますか?bashスクリプトを作成する必要があり、安全を確保したいのですが。


1
メールは1行に1語しかありませんか?
グレン・ジャックマン、2014

実際、ファイルの形式は次のとおりです。user1@ example.com example.com/user1
Pol Hallen

1
その場合、私は使用しますgrep -q '^user1@example\.com\>'-最初に行アンカー、最後に単語末アンカーを使用します。
グレン・ジャックマン、2014

回答:


24

参照してください-F(正規表現とは対照的に、固定文字列を、)および-xオプション:(行全体が一致し、正確な)。

grep -Fx user1@example.com text_file

以下と同等です:

grep '^user1@example\.com$' text_file

.任意の文字に一致する正規表現演算子であることを忘れないでください)。

-qこのような行があるかどうかだけを確認したい場合は、このオプションを使用します。

grep -Fxq user1@example.com text_file &&
  echo yes, that address is in that file.

検索する行とファイル名が可変の場合:

grep -Fxqe "$email" < "$file"

または

grep -Fxq -- "$email" < "$file"

あなたは望まない:

grep -Fxq "$email" "$file"

$emailまたはで$file開始した場合に問題が発生するため-

ファイルが(現在のロケールで、できればC)ソートされている場合は、次のcomm代わりにを使用することで、速度を上げることができますgrep

printf '%s\n' user1@example.com | comm -12 - text_file

チェックする電子メールアドレスが複数ある場合(たとえば、別のソート済みファイルにある場合)、利点はより明白になります。

comm -12 text_file emails_to_check

よりも高速になります:

grep -Fxf emails_to_check text_file

AFAIK grep -Fxq -- "$email" "$file"も機能します。
vinc17 2014

ステファン、なぜ<リダイレクターを使用してファイル入力(grepで処理)から標準入力に切り替えたのですか?何か利点はありますか?
ウムラウト

@umläuteおよびvinc17。私が言ったように、それはで始まるファイル名をカバーすること-です。でもgrep -- "$email" "$file"呼ばれるファイルのための問題だろう-(これはgrep特別な意味として扱いSTDIN
ステファンChazelas

6

できるだけ効率的にするために、最初の一致が見つかった後に停止する必要があります。あなたがGNUを持っているならgrep、これを行うことができます:

grep -m 1 '^user1@example\.com$' your_file

そうでない場合は、Perlを使用できます。

perl -nlE 'say and last if $_ eq q{user1@example.com}' your_file

4
-mGNU固有です。-qそのような行があることを効率的に確認したい場合は、POSIXを使用してください。
ステファンChazelas

3

そこにはたくさんのメールチェックがあります。それらの1つは次のとおりです。

grep -E -o "\b[a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9.-]+\b" text_file

私の答えを詳しく説明します。

^文字列の開始を示すアンカーを使用しています。メールアドレスが長い文字列の間にある場合、これは一致しません。


2
ありがとう。これは、ファイル内のすべての電子メールアドレスを「抽出」する一般的なgrepオプションです。read EMAILを使用して1つずつメールアドレスを検索してから、grepを使用して確認する必要があります。
Pol Hallen 14

2

あなたのgrepコマンドで始まるすべて一致します^user1@example.comが、また、電子メールアドレス自体を含むが、user1@example.com.spammer.com.は任意のキーに一致する正規表現の特殊文字なので、次のようにエスケープする必要があります\.

テキストファイルに1行に1つのアドレスが含まれていると仮定すると、次のように使用します。

EMAIL=user1@example\\.com
egrep "^${EMAIL}$" text_file

末尾$は、メールアドレスの後に行が終了することを確認します。"これらは変数を使用できるため、二重引用符も使用しています(単一引用符とは異なります'


1
それも一致しuser1@example-comます。
ステファンChazelas

@StéphaneChazelasあなたはもちろん正しいです。答えを更新しました。
ウムラウト

@umläuteバックスラッシュを2倍にする必要があります。ただし、を使用することをお勧めします-Fx
vinc17 14

@ vinc17、doh; bashエスケープ。とにかく、はい私はそれを使用することに優れていることに同意します-Fxが、ステファンさんの答え:-)こと
ウムラウト

0

一般的なリテラル/正確な文字列の一致を考慮:

grep -w "search_word" <file>  >  output.txt

#\b shows boundaries over here.

または、

 grep  "\bsearch_word\b"  <file>  >  output.txt 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.