shloosh
shloosh

Reputation: 595

Bash: Using quoted variable for grep within quoted expression

I'm trying to create a function within a bash script that queries a log file. Within the query function, I have something that resembles the following:

if [ -n "$(cat some-log-file.log | grep \"$1\")" ]; then
  echo "There is a match."
else
  echo "No lines matched the search term."
fi

If I send something I know will be in the log file as $1, like "I don't", I get the output:

$ ./y.sh query "I don't"
grep: don't": No such file or directory
No lines matched the search term.

If I try to single quote the $() expression, it sends the literal string and always evaluates true. I'm guessing it has something to do with the way grep interprets backslashes, but I can't figure it out. Maybe I'm overseeing something simple, but I've been at this for hours looking on forums and plugging in all kinds of strange combinations of quotes and escape characters. Any help or advice is appreciated.

Upvotes: 0

Views: 1142

Answers (1)

Jeff Bowman
Jeff Bowman

Reputation: 95704

It's actually really easy, if you realize that $() is allowed to have unescaped quotes:

if [ -n "$(cat some-log-file.log | grep "$1")" ]; then
  echo "There is a match."
else
  echo "No lines matched the search term."
fi

You can actually even skip that step, though, because grep gives an appropriate exit code:

if grep -q "$1" some-log-file.log; then
  echo "There is a match."
else
  echo "No lines matched the search term."
fi

In short, this happens for the same reason that "$1" works: Shell parameter expansion and command substitution happen before word splitting and quote removal. See more about how bash parses commands in the Shell Expansions section of the bash manual.

Upvotes: 3

Related Questions