0

I understand that special characters generate special actions:

$ echo 'abc[abc' | grep -o '['
grep: Invalid regular expression

Note that single quotes avoid issues with shell interpretation or change of the source string.

I also understand that a backslash is needed to escape that special interpretation of those special characters:

$ echo abc[abc | grep -o '\['
[

And that to match a backslash-specialChar (\[) grep needs even more backslashes:

$ echo 'abc\[abc' | grep -o '\\\['
\[

But a simple character as an f is not special and matching a \f should need no additional escape:

$ echo 'abc\fabc' | grep -o '\f'
f

But it does:

$ echo 'abc\fabc' | grep -o '\\f'
\f

A literal string, as in:

$ echo 'abc\fabc' | grep -F -o '\f'
\f

Goes to prove that the \f is being interpreted in some way by grep.

The manual states:

The ‘\’ character, when followed by certain ordinary characters, takes a special meaning:
/s
Match white space, it is a synonym for ‘[[:space:]]’.

The certain ordinary characters imply that there are other ordinary characters that are not in that list and that have no special status.

Therefore, it is my understanding that a \f (just to pick one character) should match a source string of \f.

What am I missing?

Related:

1- grep: Trailing backslash.

2- Escaping slash “\” in grep.

3- Why does sed require 3 backslashes for a regular backslash?.

2 Answers 2

1

But a simple character as an f is not special and matching a \f should need no additional escape:

$ echo 'abc\fabc' | grep -o '\f'
f

f is not special, but the backslash is special in regular expressions. The behaviour a backslash preceding a regular character varies in different utilities that implement backslash-escapes, but as for POSIX regexes, the definition states that:

The interpretation of an ordinary character preceded by an unescaped ( '\' ) is undefined, except for: [ any of (){}, 1 through 9 and inside bracket expressions ]

Similarly in extended regular expressions:

An ordinary character is any character in the supported character set, except for the ERE special characters listed in ERE Special Characters. The interpretation of an ordinary character preceded by an unescaped ( \\ ) is undefined, except in the context of a bracket expression (see ERE Bracket Expression).

grep (or rather, the regex implementation it uses) just chooses to interpret \f as the same as f. One might view that as the backslash removing any special properties of the f (even though it doesn't have any), in line with the way the backslash works in ERE. Or as an arbitrary decision.


The Linux man page regex(7) states the interpretation in clear:

An atom is [among other things] a \ followed by any other character(!) (matching that character taken as an ordinary character, as if the \ had not been present(!))

On my Mac, grep takes \f as meaning the form feed character instead, like in the C-style escape. So printf '\f' | grep '\f' matches, they both interpret it as form feed (printf is defined to do that).

1

What am I missing?

In terms of your grep string, because f is an ordinary character in regexps, '\f' is the same as 'f':

$ echo 'abc\fabc' 
abc\fabc
$ echo 'abc\fabc' | grep -o '\f'
f
$ echo 'abc\fabc' | grep -o 'f'
f

But a simple character as an f is not special and should need no escape:

$ echo 'abc\fabc' | grep -o '\f'

f

But it does:

$ echo 'abc\fabc' | grep -o '\\f'

\f

No, it doesn't. Revisiting my earlier example above:

$ echo 'abc\fabc' | grep -o 'f'
f

The man page for re_format(7) documents that the regexp \f is equivalent to the regexp f:

... a '\' followed by any other character (matching that character taken as an ordinary character, as if the '\' had not been present) ...

3
  • I understand that in the shell a backquoted character (\f) is to be interpreted as f and that the quote removal shell step will remove them. However: Where is it documented that a backslash is to be removed in grep?
    – user232326
    Oct 7, 2019 at 19:41
  • Maybe my \f example was not clearly defined, question edited. Thanks.
    – user232326
    Oct 7, 2019 at 19:44
  • @Isaac It's documented in re_format(7)
    – Jim L.
    Oct 7, 2019 at 19:50

You must log in to answer this question.