1

I usually like to echo certain string which have an exclamation point in them. And while i know how to escape them to prevent expansion by the Shell, i noticed it also print the backslash...

echo "\!" # will print \! instead of just !

Contrary to other tool like sed which does not print the backslash if used to prevent expansion of possible valid parameter used by sed:

echo "test" | sed 's/^\(.*\)$/\1 \!/' # print -> test !
echo "test" | sed 's/^\(.*\)$/\1 !/' # also print -> test !
echo "test" | sed "s/^\(.*\)$/\1 ! /" # also print -> test !, though needed to put a space or use a backslash for it to show correctly

How can i do the same with echo or I'm i obliged to use other tools like sed?

EDIT:

Just noticed using '' instead of "" with the echo example above works for printing ! without shell expansion (both with and without the backslash), though:

  • It wouldn't work in instance when one want to use command substitution with echo, since it only work with ""...
5

1 Answer 1

2

You need to escape it or quote it, not both:

echo \!
echo "!"

Bash history expansion ignores escaped exclamation marks, single-quoted exclamation marks, and exclamation marks which appear just before a closing double quote. See the History Interaction section of the manual for details. So

echo '!'

also works, and without having to think about where the exclamation mark is.

You can combine single quotes with variable expansion by using printf instead of echo. You can also combine multiple forms of quoting in the same command-line:

echo '!'"$(echo test)"

In general though, printf is better than echo. As others have mentioned you can also disable history expansion entirely; non-interactive shells don’t enable it by default.

12
  • Using echo "!" works yes, but it usually won't if used with command substitution, like so: echo "!$(echo "test")" (although it's probably because of the $ character). Any way around it? Commented Mar 25, 2021 at 15:14
  • OH, didn't thought of using printf like this! Guess that works with echo too: echo "$(echo "test")""!" yep, works! Thanks for the idea Commented Mar 25, 2021 at 15:17
  • 1
    FYI, i used the term usually loosely. eg: this doesn't work, unless you do X Y Z which i don't know/didn't thought about. Commented Mar 25, 2021 at 15:19
  • Or escape with single quotes. Which is the better way anyway, if you need something like foo!bar, or whatever where the ! isn't in one of the positions that don't trigger history expansion
    – ilkkachu
    Commented Mar 25, 2021 at 15:25
  • How safe it is to use ! inside double quotes and in which condition depends on the version of bash. Commented Mar 25, 2021 at 15:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .