1

When does history expansion happen?

  1. From bash manual

    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, ‘!’.

    Since double quotes are recognized at parsing stage by the parser, is it correct that history expansion must happen after parsing?

    If yes, when does it happen with respect to shell expansions such as brace expansion, parameter expansion, filename expansion, etc?

  2. But I think that history expansion is provided by the readline of the shell, so is processed before lexical analysis and parsing? Just like auto-completion in shell. Am I missing something?

Thanks.

2 Answers 2

7

Quoting the bash manual:

History expansion is performed immediately after a complete line is read, before the shell breaks it into words.

History expansion is the first stage of processing, even before shell parsing, which is why double quotes don’t protect !: the latter is processed before double quotes. It is handled by the history library, which implements its own parsing, with a few ways of protecting the history operator:

Only ‘\’ and ‘'’ may be used to escape the history expansion character, but the history expansion character is also treated as quoted if it immediately precedes the closing double quote in a double-quoted string.

By the time the shell’s parser starts handling a string, it’s already been parsed by the history library and history expansion has already taken place.

3
  • "... but the history expansion character is also treated as quoted if it immediately precedes the closing double quote in a double-quoted string". This doesn't appear to be the case from experience and is in direct contradiction to Bash Reference Manual: Double Quotes.
    – dev
    Oct 2, 2018 at 15:01
  • @dev, that’s a quote from the bash manual (see the link). Try echo "hello!" in bash to see what’s meant here; that works without trying to expand history. Oct 2, 2018 at 15:11
  • 1
    I'm well aware this is a quote from the manual, but for me echo "hello!" performed history expansion as usual. Your comment made me check my bash version , and guess what, I was on 3.2 (using zsh as my main shell, so bash doesn't get much love these days). Upgraded to 4.4 and we're finally on the same page. It should be noted though, that even though the manual on Double Quotes does go into the specifics of escaping !, it fails to mention the "precedes the closing double quote" case.
    – dev
    Oct 3, 2018 at 2:50
0

Just as @Stephen Kitt said, history expansion should be completed in exactly the first stage. This mode can be understood by the following things: if we type a arbitrary bash code, e.g.

echo "the value of a is $a" > tmp

Then we use use history expansion,

!-1

It's obvious that the above line will do the same thing again. What we should notice is that !-1 will be expanded to echo "the value of a is $a" > tmp first. If this expansion happens after the parsing stage, then we should realize $a will not be parsed correctly, which does not actually happen.

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.