$
is a special character for both the shell (where it's used to introduce some expansions such as $param
, $(cmdsubst)
, $((arithmetic))
) and for regular expressions (in all of basic, extended (-E
, formerly egrep
), perl (-P
/ -X perl
/ --perl-regexp
...), augmented (-X
/ --augmented-regexp
)) where it means to match at the end of the subject, so you need to escape it for both, preferably with '...'
for shells and with \$
or [$]
in regular expressions (\
and [...]
are also special in most shells and can also be quoted with '...'
):
In basic RE (without -E
/-P
/-X
...), $
is only special at the end of the regexp or in some cases before a \)
so here the regexp can be $status
, while in other regexp variants including extended ones, it's generally always special so the regexp must be \$status
or [$]status
.
Using the -F
option of grep
(formerly fgrep
) for fixed strings avoid having to do the regexp escaping. perl-like regexps also have \Q...\E
for quoting. So, many options:
grep -F '$status'
grep '$status'
grep '\$status'
grep '[$]status'
grep -E '\$status'
grep -E '[$]status'
Non-standard:
grep -P '\$status'
grep -P '[$]status'
grep -P '\Q$status\E'
grep -X '\$status'
grep -X '[$]status'
In some shells, \
and "
can also be used as quoting operators, but backslash and $
are often still special within "..."
, so that would make it awkward here. '...'
are the strongest quotes (and in some shells such as rc
and derivatives, the only quotes), so are the ones you generally want to use around regexp where many of the operators (^$*?\[](){}|
) also happen to be special in the syntax of most shells.
In any case, those will also find $status
inside
$status2
, $status_old
or $statusing
$$status
($$
followed by status
)
\$status
or any csh quoting where $status
is taken literally
And will not find
${status}
${status[1]}
(subscripting)
${status:q}
(modifiers)
$#status
or ${#status}
(number of words)
$%status
or ${%status}
(number of characters)
@ status++
/ if ( status == 0 ) then
(maths expressions where the variable may (sometimes) be used without a $
prefix).
Using a word boundary operator (\b
in perl or augmented regexp, \b
, \>
or [[:>:]]
in some implementations of BRE or ERE as non-standard extensions) would help with the first category of issues:
grep -P '\$status\b'
Without word boundary, that can be done by hand:
grep -E '\$status([^_[:alnum:]]|$)'
grep '$status\([^_[:alnum:]].*\)\{0,1\}$'
Where we look for $status
followed by either a character non-constituent of a variable name or the end of the line, or in BRE that don't have an alternation operator¹ but these days have \{0,1\}
as an equivalent of ERE ?
, $status
optionally followed by a non-variable-constituent and any number of characters up to the end of the line.
To address a few more:
grep -P '\$\{?[#%]?status\b'
grep -E '\$\{?[#%]?status([^_[:alnum:]]|$)'
grep '${\{0,1\}[#%]\{0,1\}status\([^_[:alnum:]].*\)\{0,1\}$'
¹ Though some grep
implementations have \|
for that as a non-standard extension.