David Dai
David Dai

Reputation: 1145

UNIX grep with $

I have a quick question:

Suppose I have a file contains:

abc$
$
$abc

and then I use grep "c\$" filename, then I got abc$ only. But if I use grep "c\\$", I got abc$.

I am pretty confused, doesn't back slash already turn off the special meaning of $? So grep "c\$" filename return me the line abc$?

Really hope who can kindly give me some suggestion.

Many thanks in advance.

Upvotes: 0

Views: 396

Answers (4)

rook
rook

Reputation: 6240

Sign $ has special meaning in regexp patterns as the end of line, so when you use double quotes

grep "c\$"

the string expanded as two characters c and $ and grep thinks that it is regexp clause c'mon, find all lines with 'c' at the end.

In case of singe quotes, all characters treated as each one, i.e.

grep 'c\$'

command will have three characters c, \ and $. So grep will got all those symbols at its input and therefore he gets escaped special $ symbol, i.e. as \$ and do what you have expected.

Upvotes: 0

anubhava
anubhava

Reputation: 785146

I would suggest using fgrep if you want to search for literal $ and avoid escaping $ (which means end of line):

fgrep 'abc$' <<< 'abc$'

gives this output:

abc$

PS: fgrep is same as grep -F and as per the man grep

-F, --fixed-strings Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched.

Upvotes: 0

David W.
David W.

Reputation: 107040

The double quotes are throwing you off. That allows the shell to expand meta-characters. On my Linux box using single quotes only:

$ grep 'abc$' <<<'abc$'
$ grep 'abc\$' <<<'abc$'
$ grep 'abc\$' <<<"abc$"
abc$
$ grep 'abc$' <<<'abc$'
$ grep 'abc\\$' <<<'abc$'
$ 

Note that the only grep in the five commands above that found the pattern (and printed it out) was abc\$. If I didn't escape the $, it assumed I was looking for the string abc that was anchored to the end of the line. When I put a single backslash before the $, it recognized the $ as a literal character and not as a end of line anchor.

Note that the $ as an end of line anchor has some intelligence. If I put the $ in the middle of a regular expression, it's a regular character:

$ grep 'a$bc' <<<'a$bc'
a$bc
$ grep 'a\$bc' <<<'a$bc'
a$bc

Here, it found the literal string a$bc whether or not i escaped the $.

Tried things with double quotes:

$ grep "abc\$" <<<'abc$'
$ grep "abc\\$" <<<'abc$'
abc$

The single \ escaped the $ as a end of line anchor. Putting two \\ in front escaped the $ as a non-shell meta-character and as a regular expression literal.

Upvotes: 2

devnull
devnull

Reputation: 123498

If you're tempted to think that $ need to be escaped, then it's not so.

From the GNU grep manual, you'd figure:

The meta-characters that need to be escaped while using basic regular expressions are ?, +, {, |, (, and ).

Upvotes: 1

Related Questions