Expansion of exclamation mark in single quotes in subcommand

2014-04-21 Thread Maxdamantus
version: 4.3.11(5)

This seems like a bug, but it seems to have been here for a few years
(from the git repository, bash-3.0 displays this behaviour while
bash-2.05b doesn't).

With history expansion enabled (set +H):

$ echo '!!' # good
!!
$ echo "$(echo '!!')" # not good; !! expands
echo "$(echo 'echo '!!'')"
echo !!
$ echo '$$' # good
$$
$ echo "$(echo '$$')" # good
$$



Re: Expansion of exclamation mark in single quotes in subcommand

2014-04-21 Thread Maxdamantus
After looking into the code, it turns out it's because history_expand
basically works as a finite state machine to determine whether it
should expand occurances of ! it runs into, so of course can't handle
subcommands (more specifically, quotes inside quotes). This leads to
interesting patterns though:

echo '!!' # doesn't expand
echo "$(echo '!!')" # expands
echo "$(echo "$(echo '!!')")" # doesn't expand
echo "$(echo "$(echo "$(echo '!!')")")" # expands
echo "$(echo "$(echo "$(echo "$(echo '!!')")")")" # doesn't expand

The reason it appeared to work in 2.05b was because it simply didn't
account for double quotes, which meant it had things like:
echo \' !! \' # expands
echo "'" !! "'" # doesn't expand

This seems like an architectural issue, so I probably wouldn't be able
to fix it myself (I've never looked at bash's source until
now)—logically, I'd expect the history expansion to happen in the same
place as the variable use expansion, but there must be a reason that's
not the case.



Re: Expansion of exclamation mark in single quotes in subcommand

2014-04-21 Thread Maxdamantus
> With history expansion enabled (set +H):
That should have been -H (+H disables it).



Re: Expansion of exclamation mark in single quotes in subcommand

2014-04-21 Thread Maxdamantus
It's not just inside a double-quoted block. It's inside a single-quoted block.

The last two commands in my first email demonstrate that the $
expansion is aware of that, so it follows the rule of everything
inside single-quote blocks being literal except for the single quote
itself. ! doesn't.

echo "$(echo "$$")" # here, $$ is double-quoted, so should be expanded
to something (it is)
echo "$(echo '$$')" # here, $$ is single-quoted, so shouldn't be
expand to something (it isn't)
echo "$(echo "!!")" # here, !! is double-quoted, so should be expanded
to something (it is)
echo "$(echo '!!')" # here, !! is single-quoted, so shouldn't be
expanded to something (it is—this seems wrong)

I think my second email shows even more clearly that it's a bug: each
time you nest a subcommand, the behaviour changes: it alternates
between expanding an non-expanding

On 22 April 2014 02:26, Chris Down  wrote:
> Maxdamantus writes:
>> This seems like a bug, but it seems to have been here for a few years
>> (from the git repository, bash-3.0 displays this behaviour while
>> bash-2.05b doesn't).
>>
>> With history expansion enabled (set +H):
>>
>> $ echo '!!' # good
>> !!
>> $ echo "$(echo '!!')" # not good; !! expands
>> echo "$(echo 'echo '!!'')"
>> echo !!
>> $ echo '$$' # good
>> $$
>> $ echo "$(echo '$$')" # good
>> $$
>
> I'm not totally sure why you think this is a bug. How can bash know what
> quoting style was used inside the command substitution? This is normal
> behaviour when history expansion is performed inside a double quoted
> block.
>
> Perhaps if you explained the reason you think this is a bug better,
> someone could give a more meaningful reply. :-)



Re: Expansion of exclamation mark in single quotes in subcommand

2014-04-21 Thread Maxdamantus
On 22 April 2014 04:24, Maxdamantus  wrote:
> Yeah, I can see what you're saying, but it would probably lead to the
> bash-2 behaviour, which didn't observe double quotes.
>
> Given: echo "$(echo "foo")"
> I can't see how it would be desirable for anything to consider
> '"$(echo "' and '")"' to be quoted and the rest, 'echo ' and 'foo' to
> be unquoted.
> With the bash-2 behaviour, the only quotes history expansion is aware
> of is single quotes, which can't contain another set of single quotes.
>
> It looks like the current behaviour was added into bash-3 to make
> history expansion more consistent with other expansions, but without
> realising double quotes can be nested in the somewhat separate bash
> language.
> Maybe I should show some practical-looking commands that
> (unexpectedly) runs into the problem:
>
> $ sed '3,10!d'  
> $ m="$(sed '3,10!d'  -bash: !d': event not found
>
> Ironically, this actually works if the user instead writes: m="$(!!)"
> In the process, it will print out the invalid command just above as if
> that's the one it's executing.
>
> On 22 April 2014 03:55, Chris Down  wrote:
>> Chris Down writes:
>>> !! is not single-quoted in the ultimate expansion (bash knows nothing
>>> about what happens inside the subshell), which is all that matters. It's
>>> not too late to perform history expansion (which is different than
>>> parameter expansion).
>>
>> To be more clear, the history expansion is performed immediately after
>> the line is read, before word splitting takes place.
>>
>> Perhaps this may be undesirable(?), but I don't think it's unexpected
>> behaviour.