Search code examples
regexbashgrepgnu-coreutils

grep regex with backtick matches all lines


$ cat file
anna
amma
kklks
ksklaii

$ grep '\`' file
anna
amma
kklks
ksklaii

Why? How is that match working ?


Solution

  • twm's answer provides the crucial pointer, but note that it is the sequence \`, not ` by itself that acts as the start-of-input anchor in GNU regexes.

    Thus, to match a literal backtick in a regex specified as a single-quoted shell string, you don't need any escaping at all, neither with GNU grep nor with BSD/macOS grep:

    $ { echo 'ab'; echo 'c`d'; } | grep '`'
    c`d
    

    When using double-quoted shell strings - which you should avoid for regexes, for reasons that will become obvious - things get more complicated, because you then must escape the ` for the shell's sake in order to pass it through as a literal to grep:

    $ { echo 'ab'; echo 'c`d'; } | grep "\`"
    c`d
    

    Note that, after the shell has parsed the "..." string, grep still only sees `.

    To recreate the original command with a double-quoted string with GNU grep:

    $ { echo 'ab'; echo 'c`d'; } | grep "\\\`" # !! BOTH \ and ` need \-escaping
    ab
    c`d
    

    Again, after the shell's string parsing, grep sees just \`, which to GNU grep is the start-of-the-input anchor, so all input lines match.

    • Also note that since grep processes input line by line, \` has the same effect as ^ the start-of-a-line anchor; with multi-line input, however - such as if you used grep -z to read all lines at once - \` only matches the very start of the whole string.

    To BSD/macOS grep, \` simply escapes a literal `, so it only matches input lines that contain that character.