Is it shell portable to run a command on the same line after variable assignment?

Is there any standard that covers the portability of running a command after variable assignment on the same line?

APPLE="cider" echo hi

How portable is something like that? Where will it work and where won’t it?

Also: my shell scripts start with #!/bin/sh if that makes any difference.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

As long as you’re using a POSIX compliant shell, yes.

From the POSIX definition of shell command language: (relevant points in bold)

A “simple command” is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator.

When a given simple command is required to be executed (that is, when any conditional construct such as an AND-OR list or a case statement has not bypassed the simple command), the following expansions, assignments, and redirections shall all be performed from the beginning of the command text to the end:

  1. The words that are recognized as variable assignments or redirections according to Shell Grammar Rules are saved for processing in steps 3 and 4.
  2. The words that are not variable assignments or redirections shall be expanded. If any fields remain following their expansion, the first field shall be considered the command name and remaining fields are the arguments for the command.
  3. Redirections shall be performed as described in Redirection.
  4. Each variable assignment shall be expanded for tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal prior to assigning the value.

In the preceding list, the order of steps 3 and 4 may be reversed for the processing of special built-in utilities; see Special Built-In Utilities.

If no command name results, variable assignments shall affect the current execution environment. Otherwise, the variable assignments shall be exported for the execution environment of the command and shall not affect the current execution environment (except for special built-ins).


Also, yes #!/bin/sh matters. From the POSIX definition of sh:

The sh utility is a command language interpreter that shall execute commands read from a command line string, the standard input, or a specified file. The application shall ensure that the commands to be executed are expressed in the language described in Shell Command Language.

So basically it says that sh must follow the rules we covered above.

So as long as you’re on a POSIX compliant OS, you’re good.

Method 2

To answer the second question, incompletely (the number of shells are mindboggling)

% for sh in dash ksh93 mksh rc fish bash zsh csh tcsh jsh; do
printf '%sn' "$sh: $($sh -c 'var=foo echo hi')"
done

dash: hi
ksh93: hi
mksh: hi
rc: hi
fish: Unknown command “var=foo”. Did you mean “set var foo”? For information on assigning values to variables, see the help section on the set command by typing “help set”
Standard input: var=foo echo hi
                ^
fish:
bash: hi
zsh: hi
var=foo: Command not found.
csh:
var=foo: Command not found.
tcsh:
jsh: hi

In most modern Korn-like shells, it will work. But i don’t think it is a standard, I am sure someone like Stephane Chazelas would know just how common it is.

Method 3

Yes, it’s been this way since the early days of sh

http://www.freebsd.org/cgi/man.cgi?query=sh&apropos=0&sektion=0&manpath=Unix+Seventh+Edition&arch=default&format=html

The environment for any simple-command may be
augmented by prefixing it with  one  or more
assignments to parameters.  Thus these two lines
are equivalent

      TERM=450 cmd args
      (export TERM; TERM=450; cmd args)

Method 4

Given the command in your example, echo will run, but what happens to $APPLE is a little more complicated.

It is true, as is indicated in @Patrick’s answer here, that if the shell invokes a process all variables declared on the command-line preceding its invocation are specified to be exported into its environment. And further, those variables are also specified to expire with the invoked process – so…

unset var; var=val cmd; echo ${var-unset.}

…should print unset.

But where this whole concept gets a little more complicated though, and as your own example demonstrates, is at the point that cmd is not an invoked process but is instead either a shell-builtin, a shell function, or a special shell builtin utility. In every one of those three cases the shell will most likely just run some of its own routines in memory, and invoke nothing at all.

For example, echo is almost definitely a shell builtin utility – as most shells I know of provide it as such – but it is not a POSIX-specified special builtin. In this way, it is basically a shell function that must emulate an outside executable. This is probably stated a little more clearly here:

The term “built-in” implies that the shell can execute the utility directly and does not need to search for it. An implementation may choose to make any utility a built-in; however, the special built-in utilities described here differ from regular built-in utilities…

Variable assignments specified with special built-in utilities remain in effect after the built-in completes; this shall not be the case with a regular built-in or other utility.

The special built-in utilities in this section need not be provided in a manner accessible via the exec family of functions defined in the System Interfaces volume of POSIX.1-2008.

So a variable declared on echo‘s command-line perishes with echo, but one declared on set‘s command-line persists – (though bash by default violates this rule). The same holds true when cmd is a shell function:

When a function is executed, it shall have the syntax-error and variable-assignment properties described for special built-in utilities in the enumerated list at the beginning of Special Built-In Utilities.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x