-1

file.txt:

vwive
wbvo$nivw
nowev^VWen
wev$
qnwe^

Filter lines that constains '^' in it using command :

1. grep -E "\^" file.txt

Output :

nowev^VWen
qnwe^

Filter lines that constains '$' in it using command :

2. grep -E "\$" file.txt

Output :

vwive
wbvo$nivw
nowev^VWen
wev$
qnwe^

Command 1 gives correct output by removing the special meaning of '^' but not command 2.

Why the behaviour of both command are different?

tusharRawat
  • 719
  • 10
  • 24

1 Answers1

0

Why the behaviour of both command are different?

Because the \ character is an escape character inside " quotes, and \$ is one of escape sequences. Some parts from bash manual double qoutes:

Enclosing characters in double quotes (‘"’) preserves the literal value of all characters within the quotes, with the exception of ‘$’, ‘`’, ‘\’, and, when history expansion is enabled, ‘!‘. [...]
The backslash retains its special meaning only when followed by one of the following characters: ‘$’, ‘`’, ‘"’, ‘\’, or newline.
Within double quotes, backslashes that are followed by one of these characters are removed.
Backslashes preceding characters without a special meaning are left unmodified.

The "special meaning" of \ character is meant to be the escaping thing:

A non-quoted backslash ‘\’ is the Bash escape character. It preserves the literal value of the next character that follows

Because ^ is not one of $ ` " \, then "\^" preserves both \ and ^ so it's is equal to '\^'.

Because $ is one of them, then "\$" is equal to '$'. The slash get's removed and \$ is interpreted as $.

Such typos are easy to find out with set -x.

$ ( set -x; grep -E "\$" /dev/null; )
+ grep -E '$' /dev/null
$ ( set -x; grep -E '\$' /dev/null; )
+ grep -E '\$' /dev/null
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • what if I want to use variable in regex like searching lines with 2 dot characters, would this work ? dot="." grep -E "\.\$dot" file.txt – tusharRawat Aug 07 '20 at 11:34
  • 1
    No it will not. Please take your time to learn about quoting. I would `grep -E '\.\'"$dot"` or `grep -E "\\.\\$dot"` – KamilCuk Aug 07 '20 at 11:36
  • grep -E "\.\\$dot" also works ? – tusharRawat Aug 07 '20 at 12:11
  • Yes, because `\.` is preserved – KamilCuk Aug 07 '20 at 12:20
  • But If variable expansion happens first than don't you think expression "\.\$dot" should get convert to "\.\." first and then regex matching? – tusharRawat Aug 07 '20 at 12:30
  • I do not understand. `"\$dot"` does not trigger expansion, because `\$` disables the special meaning of `$`. The expansion does not "happen first" then. Or maybe, the expansion happen only if there is a `$` has "special meaning" (ie. it triggers the expansion). Within double quotes and when preceded by "\", then `$` looses it's special meaning. – KamilCuk Aug 07 '20 at 12:32
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/219406/discussion-between-tusharrawat-and-kamilcuk). – tusharRawat Aug 07 '20 at 12:34