[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: style of assignment to variable changes command selection
From: |
Bob Proulx |
Subject: |
Re: style of assignment to variable changes command selection |
Date: |
Fri, 7 Mar 2008 23:01:28 -0700 |
User-agent: |
Mutt/1.5.13 (2006-08-11) |
Eric Blake wrote:
> Doug McIlroy wrote:
> | So there's a bug in the manual, which does not breathe a word about
> | time being executed by the shell. And the shell covers its tracks, too:
>
> Like I said, there's a difference between a builtin (for example,
> 'builtin' or 'exec') and a reserved word (for example, 'time' or 'if').
In the bash manual I am reading I see:
RESERVED WORDS
Reserved words are words that have a special meaning to the shell. The
following words are recognized as reserved when unquoted and either the
first word of a simple command (see SHELL GRAMMAR below) or the third
word of a case or for command:
! case do done elif else esac fi for function if in select then until
while { } time [[ ]]
...
If the time reserved word precedes a pipeline, the elapsed as well as
user and system time consumed by its execution are reported when the
pipeline terminates. The -p option changes the output format to that
specified by POSIX. The TIMEFORMAT variable may be set to a format
string that specifies how the timing information should be displayed;
see the description of TIMEFORMAT under Shell Variables below.
...
Pipelines
A pipeline is a sequence of one or more commands separated by the char‐
acter |. The format for a pipeline is:
[time [-p]] [ ! ] command [ | command2 ... ]
And a command is defined as:
Simple Commands
A simple command is a sequence of optional variable assignments fol‐
lowed by blank-separated words and redirections, and terminated by a
control operator. The first word specifies the command to be executed,
and is passed as argument zero. The remaining words are passed as
arguments to the invoked command.
> > % export X=x; time --version; unset X
> > -bash: --version: command not found
Here time is the shell's version because it occurs at the start of the
pipeline, which in bash does not implement a --version option to it.
> > % unset X; X=x time --version
> > GNU time 1.7
Here the environment variable assignment matches a 'command' and
therefore 'time' is an external command.
Further, because for an individual command do not affect the current
environment this implies to me that the command must have its own
environment. The manual says:
If no command name results, the variable assignments affect the current
shell environment. Otherwise, the variables are added to the environ‐
ment of the executed command and do not affect the current shell envi‐
ronment. If any of the assignments attempts to assign a value to a
readonly variable, an error occurs, and the command exits with a non-
zero status.
This implies to me that a variable assignment forces subsequent
commands to be external commands because the current environment is
not affected. In your case above the external /usr/bin/time program
is forced by the variable assignment requiring the environment
variable set for it.
> | Were I still the keeper of Unix manuals, my fix to the manual
> | would be to list this wart under BUGS.
>
> 'man bash' correctly lists time under the section RESERVED WORDS. Also,
> 'help time' gives evidence that it is special to bash (as 'help' is the
> bash builtin that reports about both reserved words and builtins).
I will leave that decision up to the maintainer. I could go either
way. However there are so many edge cases that might trip up someone
that if every one of them were documented in the bugs section then
that section would be far longer than the rest of the manual. In the
end many of these cases simply become judgement calls.
Bob