On Sunday 03 October 2010 16:45:32 Denys Vlasenko wrote:
> On Sunday 03 October 2010 22:54, Rob Landley wrote:
> > > Rob, this is not a bug. Example of bugs:
> >
> > It's inconsistent, the spec doesn't say what the correct behavior is, and
> > the behavior changes from version to version.
Oh, by the way, the bit about quotes not
> > > for v in ""; do echo "v=$v"; done # prints "v=". ok
> > > for v in "$@"""; do echo "v=$v"; done # doesnt print anything!
> >
> > How is that a bug? That's normal quote processing.
> >
> > Just as "a""b" is combined together into the single argument "ab",
> > "$...@}""x" would be combined together into "$...@}x", so "$@""" is combined
> > together into "$@" which is then expanded normally, and in the case of no
> > command line arguments expands into zero arguments.
>
> Nothing says that "abc""def" is the same as "abcdef".
You are aware that even C works that way, right?
#include <stdio.h>
char *c="one""two";
int main(int argc, char *argv[])
{
printf("c=%s\n",c);
};
It does so for slightly different reasons, but still...
And in the case of shell, the "nothing" that says this is SUSv4's "Shell
Command Language" section 2.6.7, "Quote Removal":
http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_07
> The quote characters ( <backslash>, single-quote, and double-quote) that
> were present in the original word shall be removed unless they have
> themselves been quoted.
Meaning the quotes themselves are not part of the resulting string, so
actually "abc""def" is the same as abcdef and you have to escape the quote
characters for them to be part of the resulting string.
So yes, "abc""def" and "abcdef" and just abcdef result in the same argument by
the time the implementation gets around to stuffing it into an array and
calling
execvp() or similar.
By the way, here's the bit where the spec says quoting "can prevent reserved
words from being recognized as such":
http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02
(I read all of this in great detail back in 2006. I'm a bit fuzzy on the
details, and that's before v4 came out, but still...)
> I find it extremely puzzling that "" is a word (not nothing),
If you put whitespace before and after it, yes. If you don't, then no.
> but ADDING something to it ("$@") can annihilate it!
No, it combines with an argument that isn't whitespace delimited. There's no
$IFS separating tokens, so the tokens get combined. Shell parsing 101.
It only "annihilates" it in that it appends it. In the case of $@ which has
the weird behavior of inserting token separators into something that was
previously a single token, it appends to the last argument.
Try this:
cat > temp.sh << 'EOF'
#!/bin/bash
for i in "$...@x"; do echo $i; done
EOF
chmod +x temp.sh
./temp.sh 1 2 3
> This applieds not only to explicit "", but to quoted expansion
> of variables with empty values, empty command substitutions
> like "`echo`" and such:
>
> set --
> a='a'
> for v in "$@""$a"; do echo "v=$v"; done # prints "v=a"
Correct.
> for v in "`echo`"; do echo "v=$v"; done # prints "v="
That's explained by SUSv4 2.6.3 "Command substitution":
http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_03
>The shell shall expand the command substitution by executing command in a
> subshell environment (see Shell Execution Environment ) and replacing the
> command substitution (the text of command plus the enclosing "$()" or
> backquotes) with the standard output of the command, removing sequences of
> one or more <newline> characters at the end of the substitution. Embedded
> <newline> characters before the end of the output shall not be removed;
> however, they may be treated as field delimiters and eliminated during
> field splitting, depending on the value of IFS and quoting that is in
> effect. If the output contains any null bytes, the behavior is unspecified.
Honest and truly: not a bug.
> a=''
> for v in "$@""$a"; do echo "v=$v"; done # doesn't print anything?!
> for v in "$@""`echo`"; do echo "v=$v"; done # doesn't print anything?!
>
> In my opinion, these should print nothing:
Um, the does that a= line at the top have one quote, or two?
Essentially, the argument gets crushed down to "$@" before anything else
happens, and then $@ is evaluated and can evaluate to nothing. The special
case of "$@" evaluating to no arguments is part of the definition of $@ and is
related to its ability to resolve to more than one argument: it can also
resolve to no arguments.
>From a shell parser perspective, appending an empty string to $@ is
indistinguishable to having an empty string before and after it to begin with
simply by the act of quoting it. The string "$@" has an empty string before
the $@ and another one after the $...@. That's normal. It's like doing
strcat(x,""); It's a NOP.
> a=''
> for v in "$@"$a; do echo "v=$v"; done
> for v in "$@"; do echo "v=$v"; done
>
> But these should print "v=":
Um, both of them...?
Again, a=" with no closing quote isn't a valid line, it would continue into
the next line and you'd wind up with an odd number of quotes and I'm confused
what you're trying to show here.
But there honestly is an SUSv4 spec that defines the order of operations
here...
> a=''
> for v in "$@""$a"; do echo "v=$v"; done
> for v in "$@"""; do echo "v=$v"; done
>
> This just makes more sense regarding usual rules of expansion
> of quoted and unquoted strings: quoted string never vanish
> unless it's "$@", while unquoted one can vanish.
>
> The fun part is that hush _does_ match bash here - just because
> this quirky/buggy behaviour is easier to code.
> It "comes out natually".
> I guess bash does this for the same reason.
You're having a weird fetish about corner cases when you apparently have read
(or didn't understand) the spec. I was complaining that features were
entirely missing. I think we're talking past each other.
> > > I believe I implemented brace expansion in hush so that it passes
> > > all three these tests:
> > >
> > > v='/bin/*'; echo $v
> > > v='/bin/{a,b}*'; echo $v
> > > echo /bin/{a,b}*
> >
> > I guess I should go report the inconsistent behavior to the bash people
> > now, and let them evaluate the inconsistency. They might fix it in the
> > next version, in which case you can claim you're compatible with older
> > versions of bash but not the current one.
>
> Well, I'd like you to try current git's hush :D
It's on the todo list.
Rob
--
GPLv3: as worthy a successor as The Phantom Menace, as timely as Duke Nukem
Forever, and as welcome as New Coke.
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox