'Why does line comment tricks for bash not work with exclamation mark "!"
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
Solution 1:[1]
(The following explanation turned out to be WRONG though it explained everything. See the UPDATE as follows.)
# !xxxThis works as expected because
!is in the comment.echo # !xxxThis also works as expected because
!is also in the comment.echo `true # !xxx`This also works because
!is still in the comment, though it's in the`...`context.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 likeecho `COMMAND !xxx`.echo `# # !xxx`Why does this work?
As explained in #4, the first
#is parsed as a COMMAND so it's just likeecho `COMMAND # !xxx`so now!is in the comment.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 likeecho `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 foundWell, 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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
