0

I've just come across !$ (without quotes). I've not met this before and did some tests:

$ ls -l
(...some output...)
$ echo !$
-l
$ echo "!$"
-l

man bash says this in the section on history expansion:

$ The last word. This is usually the last argument, but will expand to the zeroth word if there is only one word in the line.

Fair enough. But should I quote it or not? Another test on history expansion leaves me in doubt:

$ man bash
$ "!!"
"man bash"
bash: man bash: command not found

This could be expected. But then, what about !$? This is one word, so I guess it should be quoted...

(I'll risk this new tag here: .)

  • What are you trying to accomplish? If you want to use it in an echo then it should probably be quoted since the last word of the previous command could be something like -n which would change the behavior of the echo command. If you want that behavior than you shouldn't quote it. Am I missing a deeper part of your question? – David King May 21 '18 at 19:53
  • @DavidKing Just learning... And your reasoning is not correct. Quoted parameters are still parameters. Check it. – Tomasz May 21 '18 at 19:55
  • You're right. I never noticed that before. In that case it really shouldn't matter if you quote it or not. – David King May 21 '18 at 19:59
2

It depends on if you want to add a set of quotes around the word from history expansion, or not.

Assuming foo="abc def", compare

$ echo $foo
$ printf "<%s>\n" !$

vs.

$ echo $foo
$ printf "<%s>\n" "!$"

The former produces printf "<%s>\n" $foo, invoking word splitting, and printf gets two arguments after the format string. The second produces printf "<%s>\n" "$foo", where the quotes prevent word splitting, as usual.

Of course, if you were to do this:

$ echo "$foo"

Then a !$ on a following command would already expand to "$foo", with the quotes already in place. Now, using "!$" would produce ""!$"", where the quotes effectively cancel each other.

  • @Tomasz, from the initial $ signs at the start of the lines here? You're not really supposed to include them in the command, they are customarily used to signify the prompt, meaning that the following part is a command and the lines without them are output from the commands. They do make copy-pasting commands a bit harder, though... – ilkkachu May 21 '18 at 21:13
  • @Tomasz, I'm not sure if some HTML/CSS trickery could be used to make selections only hit certain parts of text, so that it would be easy to just copy the commands from code examples, and not their output. But the site doesn't support that. And some might say it's better to not make copypasting shell commands too easy. – ilkkachu May 21 '18 at 21:20
  • Maybe I did this automatically, as there was no output? I might have left my first comment, so someone might benefit. You can restore it if you have those powers. There's this JS on SO: stackoverflow.blog/2014/09/16/… It will take a while before we get similar Bash stuff here. – Tomasz May 21 '18 at 21:32
2

History substitution retrieves whatever was parsed as the last word, quotes and all,

$ echo this that "the other"
this that the other
$ echo !$
the other

and it runs first, so you can retrieve and rerun other substitutions

$ echo `date`
Mon May 21 13:53:37 PDT 2018
$ echo !$
Mon May 21 13:53:38 PDT 2018

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.