10

by way of example, I've a big text file with many email address, using bash I need search/verify that an email exists (or no). Should be use (only) the "anchors"?

grep '^[email protected]' text_file

or there're better ways? I need create a bash script and I'd like be safe.

4

5 Answers 5

26

See the -F (fixed string, as opposed to regular expression) and -x (exact: match the whole line) options.

grep -Fx [email protected] text_file

would be the equivalent of:

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

(remember that . is a regular expression operator that matches any character).

Use the -q option if you only want to check if there's such a line:

grep -Fxq [email protected] text_file &&
  echo yes, that address is in that file.

If the line to search and the file name are variable:

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

Or

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

You don't want:

grep -Fxq "$email" "$file"

as that would cause problems if $email or $file started with -.

If the file is sorted (in your current locale, preferably C), you can possibly speed things up by using comm instead of grep:

printf '%s\n' [email protected] | comm -12 - text_file

The advantage will become more obvious when you have several email addresses to check (for instance in another sorted file):

comm -12 text_file emails_to_check

would be faster than:

grep -Fxf emails_to_check text_file
3
  • AFAIK, grep -Fxq -- "$email" "$file" also works.
    – vinc17
    Jul 24, 2014 at 13:28
  • stephane, why did you switch from a file input (handled by grep) to stdin using the < redirector? are there any advantages?
    – umläute
    Jul 24, 2014 at 13:30
  • @umläute and vinc17. As I said, it's to cover for filenames starting with -. even grep -- "$email" "$file" would be a problem for a file called - (which grep treats specially as meaning stdin) Jul 24, 2014 at 14:08
6

To be as efficient as possible, you want to stop after the first match is found. If you have GNU grep, you can do this:

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

If you don't, you can use Perl:

perl -nlE 'say and last if $_ eq q{[email protected]}' your_file
1
  • 4
    -m is GNU specific. Use the POSIX -q if you want to efficiently check that there's such a line. Jul 24, 2014 at 13:12
3

There are a lot of email checks there. One of those is:

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

To elaborate my answer.

You are using the ^ anchor which indicates the start of the string. This won't match if an email address is somewhere in between a long string.

1
  • 2
    Thanks. That's is a generic grep options to "extract" all email address inside a file. I need searching for one by one email address using read EMAIL then using grep to check it.
    – Pol Hallen
    Jul 24, 2014 at 13:01
2

your grep command will match everything that starts with ^[email protected], including the email address itself, but also [email protected]. since . is a special character in regular expressions that matches any key, you should escape it as \.

assuming that your textfile contains one address per line, use:

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

the trailing $ will make sure that the line ends after the email-address. i'm also using double-quotes ", as these allow to use variables (unlike single-quotes ')

4
  • 1
    That also matches user1@example-com. Jul 24, 2014 at 13:09
  • @StéphaneChazelas you're of course right; updated the answer.
    – umläute
    Jul 24, 2014 at 13:28
  • @umläute You need to double the backslash. But it's better to use -Fx.
    – vinc17
    Jul 24, 2014 at 13:33
  • @vinc17, doh; bash escaping; anyhow, yes i agree that it is better to use -Fx but that's stephane's answer :-)
    – umläute
    Jul 24, 2014 at 13:36
0

Considering general literal/exact string match:

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

#\b shows boundaries over here.

or,

 grep  "\bsearch_word\b"  <file>  >  output.txt 

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .