Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

Does grep distinguish a variable and the $ regex?

Writer Matthew Barrera

I want to grep for a variable that has the string test, but I also want to make sure that it will only find test if that is the only word on a line.

So, I tried this:

string=test
echo "test" | grep "$string$"

I would like to know if grep knows that the first part, $string (in grep "$string$"), is asking to find for the string test, while the last part, $ (in grep "$string $" is asking to find for test, but nothing should be after test in the line. Is grep able to distinguish $string as a variable and only $ as the regex for end of the line, or do I have to use a certain way to distinguish them apart?

1 Answer

Grep knows nothing it does not see. If grep sees $string$, it will try to match $string{end-of-line}. What happens is that the shell expands the variable $string before grep kicks in, so that grep receivestest$ as the regex.

But, given the word $string$, why is the last $ is not expanded while$string is? Because $ is not a valid variable name. This is very clear in the POSIX specification:

If the parameter is not enclosed in braces, and is a name,the expansion shall use the longest valid name (see XBD Name), whether or not the variable represented by that name exists.

And XBD name states

In the shell command language, a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit.

And there are also special parameters, such as $$, $@, $#, etc..

If you don't want to remember all this, simply follow Gordon Davisson's adviceand escape every $ that should not introduce a variable to ensure it will be preserved.

$ echo "$string$"
test$
$ echo "$string\$"
test$
$ echo "\$string\$"
$string$

Also remember variables are expanded in double-quotes but not in single quotes.

$ echo 'test' | grep '$string$' # No match, $string is not expanded
$ echo 'test' | grep "$string$" # Match, $string is expanded
test

I want to grep for a variable that has the string test, but I also want to make sure that it will only find test if that is the only word on a line.

For that, you need either the regex ^test$ (to anchor the string both to the start and end of line) or to use the -x flag of grep. Your original attempt would match Atest because the regex test$ is not anchored to the start of line.

$ echo Atest | grep "$string$"
Atest
$ echo Atest | grep -x "$string"
$ echo Atest | grep "^$string$"
3

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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