简体   繁体   中英

Confusing shell syntax

In one of the examples from Kernighan & Pike, The Unix Programming Environment , the authors do a variable assignment in the same line as a command. The line goes like this:

if PATH=$opath "$@" >$new

where the value of those variables before this line is:

PATH=/bin:/usr/bin

and opath=/a/really:/long/list/of:/pathnames

What confuses me is that when I change that line around to

if PATH=$opath echo $PATH

The stdout is:

/bin:/usr/bin

I've confirmed this in both sh and bash. Can anyone please educate me as to what Kearnighan & Pike were doing here? Has this aspect of shell implementation changed since 1982 or is something else going on?

edit: This is the whole program from the book.

#!/bin/bash

# overwrite: copy standard input to output after EOF
# final version

opath=$PATH
PATH=/bin:/usr/bin

case $# in
0|1)        echo 'Usage: overwrite file cmd [args]' 1>&2; exit 2
esac

file=$1; shift
new=/tmp/overwr1.$$; old=/tmp/overwr2.$$
trap 'rm -f $new $old; exit 1' 1 2 15

if PATH=$opath "$@" >$new
then
    cp $file $old
    trap '' 1 2 15
    cp $new $file
else
    echo "overwrite: $1 failed, $file unchanged" 1>&2
    exit 1
fi
rm -f $new $old

I understand what the program is doing, and how the if condition will evaluate to true if the exit status of "$@" >$new is 0. What I don't understand is why PATH is not assigned the value of $opath within the "if" line in question.

The expansions that shell performs on

PATH=$opath echo $PATH

are (in this order):

  1. Expand $PATH into its current value
  2. Expand $opath into its value
  3. Execute the echo command in the environment where PATH equals the expansion of $opath .

So the command sees the modified value of PATH , but the assignment doesn't affect the expansions performed by the shell.

Moreover, even subsequent commands won't see the new value of $opath , it's confined to the current command only.

This logic changes when the command part is empty (ie there's just an assignment);

PATH=$opath
echo $PATH

will first change the value of $PATH in the current execution environment, and then print the new value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM