I was trying to find a way to know the emails written in source codes. I found a way to get the information I was looking for using grep, but as I'm not really familiar with grep syntax I'm looking at how it could be done with sed for the futur. What I did with grep is:

grep [0-9a-zA-Z]@[0-9a-zA-Z] ./ -r | \
grep -o '[[:alnum:]+\.\_\-]*@[[:alnum:]+\.\_\-]*' | \
sort | uniq -c | sort -n

That (second) grep expression is found on the net and have a bunch of miss matches.

My sed expression so far was:

grep -h [0-9a-zA-Z]@[0-9a-zA-Z] ./ -r | \
sed -nre 's/.*\([a-zA-Z0-9\.]*@[a-zA-Z0-9\.]*\).*/\1/p' | \
sort | uniq -c | sort -n

The problem with it is that sed regex are greedy. I thought of using /expression/s/.*/\1/, but sed does not find \1, as I guess the matches are limited to the .*.

  • 6
    It would help if you'd add a sample of the content and the expected output. Feb 23 '20 at 0:00

Use grep:

grep -rhoE '[[:alnum:].!#$%&'\''*+/=?^_`{|}~-]+@[[:alnum:].]+' .

or perhaps:

grep -rhoP '(?:[a-z0-9!#$%&'\''*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'\''*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])' .

(based on info found at stackoverflow)

Regarding the question:

  • Instead of using .* try negating the character class used in the subexpression. Eg:
sed -nE -e 's/[^[:alnum:]._-]*([[:alnum:]._-]+@[[:alnum:]._-]+)[^[:alnum:]._-]*/\1\
  • The dot does not need te bu escaped in a character class (the backslash is literal inside the class). You could use [^[:alnum:].-] for less typing. Also note that inserting newlines with the s command in sed is supported by GNU sed only (likewise, your grep example at the end requires GNU grep). There is also [[:punct:]] to match punctuation characters.
    – Kusalananda
    Feb 23 '20 at 8:01

FWIW I use this ERE (so it'll work in grep -E, sed -E, awk, perl, etc.):


based on the regexp at http://www.regular-expressions.info/email.html. Add word boundaries if your tool supports them, without sample input/output I can't suggest anything else to bound the email addresses. I specifically do not use character classes so I only get English letters as that's what works best for my application.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.