[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Command substition failure?
From: |
Michael Witten |
Subject: |
Re: Command substition failure? |
Date: |
Sat, 02 Apr 2011 21:59:15 +0200 |
On Sat, 02 Apr 2011 15:20:23 +0200, Andreas Schwab wrote:
>> Could somebody please tell me what's going on here?
>
> Brace expansion.
>
> $ set -x
> $ echo "$(echo '"' | awk '{sub(/a/,$0)}')"
> ++ echo '"'
> ++ awk 'sub(/a/'
> awk: cmd. line:1: sub(/a/
> awk: cmd. line:1: ^ unexpected newline or end of string
> ++ echo '"'
> ++ awk '$0)'
> awk: $0)
> awk: ^ syntax error
> + echo '' ''
So, basically, bash is viewing this:
echo "$(echo '"' | awk '{sub(/a/,$0)}')"
as:
echo PREAMBLE{x,y}POSTSCRIPT
where PREAMBLE is the string:
"$(echo '"' | awk '
and the `x' is the string:
sub(/a/
and the `y' is the string:
$0)
and the POSTSCRIPT is the string:
')"
Thus, bash expands the line to the following:
echo "$(echo '"' | awk 'sub(/a/')" "$(echo '"' | awk '$0)')"
Bash runs the first substitution command:
echo '"' | awk 'sub(/a/'
which fails with:
awk: cmd. line:1: sub(/a/
awk: cmd. line:1: ^ unexpected newline or end of string
and produces an empty string as output.
Bash runs the second substitution command:
echo '"' | awk '$0)'
which fails with:
awk: $0)
awk: ^ syntax error
and produces an empty string as output.
Thus, the whole line becomes:
echo "" ""
which outputs 2 characters: A space followed by a newline.
Phew!
OK, now, I think that's a bug!
The bash manual here:
info '(bash)Brace Expansion'
or here:
http://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html#Brace-Expansion
says:
3.5.1 Brace Expansion
---------------------
...
A sequence expression takes the form `{X..Y[..INCR]}', where X and Y
are either integers or single characters, and INCR, an optional
increment, is an integer...
Brace expansion is performed before any other expansions,
and any characters special to other expansions are preserved
in the result. It is strictly textual. Bash does not apply any
syntactic interpretation to the context of the expansion or
the text between the braces. To avoid conflicts with parameter
expansion, the string `${' is not considered eligible for brace
expansion.
A correctly-formed brace expansion must contain unquoted
opening and closing braces, and at least one unquoted comma
or a valid sequence expression. Any incorrectly formed brace
expansion is left unchanged.
A { or `,' may be quoted with a backslash to prevent its
being considered part of a brace expression. To avoid conflicts
with parameter expansion, the string `${' is not considered
eligible for brace expansion.
...
In particular:
A correctly-formed brace expansion must contain unquoted
opening and closing braces, and at least one unquoted comma
or a valid sequence expression. Any incorrectly formed brace
expansion is left unchanged.
Now, my email with `Message-ID':
ecdf0813-3e67-4bb7-bfaf-6bfc12336c31-mfwitten@gmail.com
shows:
The input characters within the quoted string
that are also enclosed between "$(" and the
matching ')' shall not be affected by the
double-quotes, but rather shall define that
command whose output replaces the "$(...)" when
the word is expanded.
and this:
... When using the `$(COMMAND)' form, all characters between
the parentheses make up the command; none are treated
specially.
So, there should be no brace expansion in this case, because
the entire brace construct is quoted:
'{sub(/a/,$0)}'
Thus, bash has a bug.
My guess is the nature of the problem is that the combination
of the outer-most quotes (which would render most characters
as literal) and the command substitution (which in some sense
is probably parsed in a `top-level' context) works to confuse
the brace-expansion logic.
Sincerely,
Michael Witteng