Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > gnu.bash.bug > #15270

Re: x[

From Martijn Dekker <martijn@inlv.org>
Newsgroups gnu.bash.bug
Subject Re: x[
Date 2019-07-30 00:01 +0200
Message-ID <mailman.201.1564437695.1985.bug-bash@gnu.org> (permalink)
References <CAAZkfoK2hYq_qSkdKYc1on=+V4VEBgpgZW96sYNZwC+AMw7iTw@mail.gmail.com> <9EA25AF1-6D80-456A-81FA-6D908072E624@gmail.com> <a6a2b6a8-6151-78dc-41be-fc81250a40e5@archlinux.org> <db16f8b8-2a6d-a894-799d-f31827e72d92@inlv.org>

Show all headers | View raw


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

Back to gnu.bash.bug | Previous | Next | Find similar | Unroll thread


Thread

Re: x[ Martijn Dekker <martijn@inlv.org> - 2019-07-30 00:01 +0200

csiph-web