Why do I have to quote an escaped character in a regular expression for grep, but not on online regex engines?
Why? because your shell interprets some special characters, such as \
in your example.
You are running into troubles because you do not protect the string that you try to pass as argument to grep via the Shell.
Several solutions:
- singlequoting the string,
- doublequoting the string (with doublequoting the shell will interpret several things, such as
$variables
, before sending the resulting string to the command), - or not use quoting (which I strongly advise against) but add backslashes in the right places to prevent the shell to interpret the next characters before sending it to the command.
I recommend to protect the string via single quotes, as it keeps almost everything literraly:
grep '9\.0' #send those 4 characters to grep in a single argument
The Shell pass the singlequoted string literally.
Note: The only thing you can't include inside a single quoted shell string is a single quote (as this ends the singlequoting). To include a singlequote inside a singlequoted shell string, you need to first end the singlequoting, immediately add an escaped singlequote
\'
(or one between doublequotes:"'"
) and then immediately reenter the singlequoting to continue the single quoted string : for exemple to have the shell execute the commandgrep a'b
, you could write the parameter as'a'\''b'
so that the shell sendsa'b
to grep: so write:grep 'a'\''b'
, orgrep 'a'"'"'b'
If you insist on not using quoting, you need your shell to have a \\
to have it send a \
to grep.
grep 9\\.0 # ie: a 9, a pair \\, a ., and a 0 , and the shell interprets the pair \\ into a literal \
If you use doublequotes: you need to take into account that the shell will interprets several things first ($vars
, \
, etc). for exemple when it sees an unescaped or unquoted \
, it waits the next character to decide how to interpret it. \w
is seen as a single letter w
, \\
is seen as a single letter \
, etc.
grep "9\\.0" # looks here the same as not quoting at all...
#but doublequoting allows you to have spaces, etc, inside the string
Turning the comments into an answer:
The problem is that \
is the escape character both for regexes and the shell. \.
is to the shell the same as '.'
. echo
and set -x
help understand, what the shell does:
> echo \.
.
> echo '\.'
\.
> echo \\.
\.
> set -x
> echo 9_00 | grep 9\.00
+ echo 9_00
+ grep 9.00
9_00
So if the command shall see the \
then it has to be protected by quotes or a second \
.
To add to the other answer and comments, another thing that you can do to get grep
to return what you want is to use the following:
grep -F 9.00 small.txt
Output:
9.00
The -F
makes grep
see the pattern as a fixed string and not a regular expression so that it will only return lines with that exact string. Because of this, you don't even need to escape the .
or use quotes because it will only match 9.00
exactly instead of seeing the .
as any character.