[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: x[
From: |
Martijn Dekker |
Subject: |
Re: x[ |
Date: |
Tue, 30 Jul 2019 00:01:17 +0200 |
User-agent: |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 |
Op 29-07-19 om 19:09 schreef Eli Schwartz:
The initial workaround discovered, was to use
$ function _[ () { echo hello; }; <() _[
hello
The use of <() somehow suppresses the glitch in the same way that
quoting it does. If it were just glob expansion, then why should that be so?
As others pointed out, it's the start of an array assignment, and
associative array indexes can contain newlines.
So we can de-obfuscate the issue by looking at a simple variable
assignment 'x=foo' instead. Consider:
$ function x=foo { echo hello; }; <() x=foo
hello
However:
$ function x=foo { echo hello; }; </dev/null x=foo
(no output)
$ echo $x
foo
In that case, 'x=foo' is interpreted as an assignment. Which is correct,
because redirections can occur in any word of a simple command,
including before and between assignments and arguments. They are
performed and removed before further parsing and executing the command.
<(Process substitution) may look superficially like a fancy form of
redirection[*], but it's actually more akin to command substitution: the
command inside is run, and the substitution is replaced, not with that
command's output, but with a file name from which to read that command's
output (or, in the case of >(process substitution), a file name to which
to write that command's input).
Because that command is empty in this instance, bash does not bother to
substitute a file name, and the <() is substituted by nothing.
So, let's get rid of the function (because it is a distraction) and just
see how 'x=foo' is parsed in substitutions and redirections:
$ <() x=foo
bash: x=foo: command not found
$ $() x=foo
bash: x=foo: command not found
$ `` x=foo
bash: x=foo: command not found
$ </dev/null x=foo
(no output)
Here it is also important to understand that a "simple command" consists
of either assignments, or command words, or both:
x=foo y=bar some command here
So, both process substitution and command substitution (both forms)
signal to the parser that the preceding assignments in a simple command
have ended, and we're now on to command words and thus trying to execute
a command called 'x=foo'. This is also true on simple POSIX shells like
dash (for command substitution -- they don't have process substitution).
The fact that the substitutions are empty, and thus substituted by
nothing, does not stop them from influencing the parser.
The same is not true for redirections, which are specified by POSIX to
be parsed and removed at the earliest stage, before even distinguishing
between assignments and command words.
- M.
[*] Pointless lament: It's unfortunate that process substitution starts
with '<' or '>' and not with $ like every other kind of substitution and
expansion (except obsolete `command substitutions`). It confuses people
into thinking of it in terms of redirection, which is very misleading.
By the way, in modernish, I've re-implemented process substitution in a
form usable by all POSIX shells (including simple ones like dash), as a
form of command substitution:
$( % your command here ) # like <(your command here)
$( % -o your command here ) # like >(your command here)
--
modernish -- harness the shell
https://github.com/modernish/modernish
- x[, Isabella Bosia, 2019/07/29
- Re: x[, Clint Hepner, 2019/07/29
- Re: x[, Eli Schwartz, 2019/07/29
- Re: x[, Greg Wooledge, 2019/07/29
- Re: x[,
Martijn Dekker <=
- Re: x[, Eli Schwartz, 2019/07/29
- Re: x[, Koichi Murase, 2019/07/29
Message not available
- Re: x[, Stephane Chazelas, 2019/07/29
Re: x[, Chet Ramey, 2019/07/29