Quotes when using grep?

23,134

Solution 1

The command line including the arguments is processed by the shell before it is executed. You can use echo to see what the shell does:

$ echo grep -e show\(  test.txt 
grep -e show( test.txt

$ echo grep -e "show\("  test.txt 
grep -e show\( test.txt

$ echo grep -e 'show\('  test.txt 
grep -e show\( test.txt

So without quotes the backslash gets removed making the "(" a normal character for grep (grep uses basic regex by default, use -E to make grep use extended regex).

Solution 2

In order:

grep -e show( test.txt

does not work, because the shell interprets the ( as special, a parenthesis, not just a character, and can't find the closing ).

These both work:

grep -e 'show(' test.txt
grep -e "show(" test.txt

because the shell treats the quoted text as just text, and passes it to grep.

These do not work:

grep -e 'show\(' test.txt
grep -e "show\(" test.txt

because the shell passes show\( to grep, grep sees \( as special, a parenthesis, not just a character, and can't find the closing \).

Solution 3

The quotes change what grep sees. The backslash (\) in the un-quoted form is processed by the shell, which treats characters after the backslash as special. This happens before grep gets the parameter. grep sees show(. When the quotes (single or double) are used, the shell interprets them as "leave the contents alone", thus grep sees show\( and the \( characters have meaning in grep and it is looking for the closing parenthesis - \).

BTW: Single and double quote handling is different in how the shell handles shell variables, but there are no shell variables in your example.

Share:
23,134
Hamy
Author by

Hamy

Updated on June 10, 2020

Comments

  • Hamy
    Hamy almost 4 years

    Grep acts differently depending on what kind of quotes I surround the regex with. I can't seem to get a clear understanding of why this is. Here is an example of the problem:

    hamiltont$ grep -e show\(  test.txt 
      variable.show();
      variable.show(a);
      variable.show(abc, 132);
      variableshow();
    hamiltont$ grep -e "show\("  test.txt 
    grep: Unmatched ( or \(
    hamiltont$ grep -e 'show\('  test.txt 
    grep: Unmatched ( or \(
    

    I am just assuming there is some proper way to enclose the regex with single/double quotes. Any help?

    FWIW, grep --version returns grep (GNU grep) 2.5.1

  • Maria Ines Parnisari
    Maria Ines Parnisari over 10 years
    I still don't get what is the difference between single and double quotes. In the example you posted, they seem to do the same thing.
  • tonix
    tonix over 8 years
    What if I have a grep regex that should match a single quote or a double quote, how can I write it with grep? grep '["]\'" doesn't seem work...
  • pd12
    pd12 over 8 years
    single and double quotes do the same thing for our purposes. To match a quote just use " or '. If surrounding the pattern in quotes, use the different quote to the one you want to match, e.g. matching " within a pattern would be 'foo"bar'
  • pd12
    pd12 over 8 years
    For both types of quotes inside pattern, use single quotes around outer command and escape with \' see unix.stackexchange.com/questions/23347/…
  • Charles Duffy
    Charles Duffy almost 2 years
    In this specific case echo is sufficient to show what the shell is doing, but very, very often it is not (and for someone to know a priori if echo would be sufficient, they would need to understand shell parsing enough to not need to ask the question at all). For example, one can't use echo to tell the difference between echo "hello world" and echo "hello" "world". It's a better habit to teach people to use set -x, or even printcmd() { printf '%q ' "$@"; echo; } and then printcmd grep -e show\( test.txt. (In bash 5, printcmd() { echo "${@@Q}"; } is a shorter alternative).