Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does line comment tricks for bash not work with exclamation mark "!"

Tags:

ref Inline comments for Bash?

We can use this tricks

echo abc `#put your comment here` \
     def `#another chance for a comment` \
     xyz etc

but these do not work if we have an exclamation mark in comment

echo 1 `# 2 !3`
<error>
-bash: !3: event not found

if we type it directly it will not be translated to an event

# 2 !3
<that is OK>

It seams that we need an other # symbol to workaround it.

echo 1 `# 2 #!3`
<that is OK>
1

or do we have to double the leading # symbol?

echo 1 `# # 2 !3`
<that is OK>
1
like image 353
William Leung Avatar asked Feb 11 '20 09:02

William Leung


People also ask

What does exclamation mark do in bash?

Bash maintains the history of the commands executed in the current session. We can use the exclamation mark (!) to execute specific commands from the history.

How do I escape exclamation mark in bash?

Bash script (detect.sh) When an argument contains a special character (for example, an exclamation point) you must escape the character with a backslash. The backslash should precede the escaped character.

How do you grep with an exclamation mark?

at the start of a pattern, by either using a backslash ( \! ), or otherwise making it not the first character of the regex ( /[!] , for example).

How do you use an exclamation mark in Linux?

Exclamation mark is for "Not" (like in boolean), -d flag is for folder exists in bash.


1 Answers

(The following explanation turned out to be WRONG though it explained everything. See the UPDATE as follows.)

  1. # !xxx

    This works as expected because ! is in the comment.

  2. echo # !xxx

    This also works as expected because ! is also in the comment.

  3. echo `true # !xxx`

    This also works because ! is still in the comment, though it's in the `...` context.

  4. echo `# !xxx`

    Why doesn't this work?

    I guess there's a little bug when Bash interprets the `...` part. In `...`, Bash always assumes (wrongly) the first WORD is a COMMAND name so it does not think ! is in a comment and so history expansion is triggered. That's to say, echo `# !xxx` is just like echo `COMMAND !xxx`.

  5. echo `# # !xxx`

    Why does this work?

    As explained in #4, the first # is parsed as a COMMAND so it's just like echo `COMMAND # !xxx` so now ! is in the comment.

  6. echo `## !xxx`

    This double hash does not work either.

    As explained in #4 and #5, here ## is the first WORD and it's parsed as the COMMAND name so it's also like echo `COMMAND !xxx`.

Note that, in the `...` context, the bug is only in the first round syntax parser. That's to say, even though Bash initially parses the # as a COMMAND name, it does not really run it as a command which is named #.


UPDATE 2020-03-04

The above explanation turned out to be WRONG though it explained everything. Please see the discussion in bug-bash mailing list.

I'd quote Chet's explanation here for easy reference:

> $ set -H
> $ true `# !xxx`
> bash: !xxx`: event not found

Well, the history comment character (#) is not found at the start of a word (here # is part of the word `#), so the rest of the line is processed for history expansion.

$ true `# # !xxx`

The history comment character is found at the start of a word (here the 2nd # itself is a word) and history expansion skips the rest of the line.

Readline history expansion knows very little about shell syntax; in particular, it doesn't know backquotes. It never has.

like image 78
pynexj Avatar answered Oct 05 '22 20:10

pynexj