I've got a bash script that cleans up the mail queue periodically. For Reasons, we've elected to delete any email to @mms.att.net and other email2SMS gateways that are over 9 hours in the queue and still not delivered.
Simplified, the script does this:
domains=`cat /etc/mail/email2textdomains.txt`
egrep $domains /var/log/maillog | .... other tasks
and the content of /etc/mail/email2textdomains.txt
is exactly
"mms.att.net|vtxt.com|vtext.com|vzwpix.com"
So the egrep line should be this, which is exactly what I'd type at the command line.
egrep "mms.att.net|vtxt.com|vtext.com|vzwpix.com" file | ...
If I ran it like this, then it's a 5+ stage pipeline of commands each reading stdin from the previous stdout. This is clearly not the search I want to do.
egrep mms.att.net|vtxt.com|vtext.com|vzwpix.com file | ...
However when run, the two double quotes are treated differently - they become part of the string, so we're essentially searching for
- "mms.att.net
- vtxt.com
- vtext.com
- vzwpix.com"
Clearly I've misunderstood how quoting works - the resolution was to change the included line to remove the double quotes, resulting in a line that should not work, but does.
I've tried testing by piping to od -a
which does not show any non-printing characters.
Why does it work, making the content of /etc/mail/email2textdomains.txt
is exactly
mms.att.net|vtxt.com|vtext.com|vzwpix.com
when it should be a long pipeline to failure as written?
var=$(cat file)
will put the quotes intovar
. The quotes are data, and not code.var="abc"
puts onlyabc
intovar
, because those quotes are shell syntax. Quotes that arise from variable substitution, likeegrep $domains
are also not syntax, but data.eval egrep $domains
should do it, if you're confident that the file contains valid shell syntax with no injection pitfalls. Theeval
command will re-process the entire substitution and expansion as shell syntax and thus recognize the quotes.egrep
, usegrep -E
. 2. double-quote$domains
on thegrep -E
command line. 3. better yet, there's no need for command substitution here, grep has-f
option for reading the pattern list from a file (e.g.grep -f /etc/mail/email2textdomains.txt /var/log/maillog
. 4. since this is a list of domains with.
s in them, it would probably a good idea to use grep's-F
option for fixed strings rather than regexes and-w
for "whole-word" matches....otherwise you get false positives likevtext.com
matching domains likesomevtextycomputer.net
becausevtextycom
matches.