令人困惑的shell语法

Jon*_*ler 1 unix linux bash shell

在来自Kernighan&Pike,Unix编程环境的一个例子中,作者在与命令相同的行中进行变量赋值.这条线是这样的:

if PATH=$opath "$@" >$new
Run Code Online (Sandbox Code Playgroud)

其中此行之前的变量值为:

PATH =/bin中:在/ usr/bin中

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

令我困惑的是,当我改变那条线时

if PATH=$opath echo $PATH
Run Code Online (Sandbox Code Playgroud)

标准输出是:

/斌:在/ usr/bin中

我已经在sh和bash中证实了这一点.谁能教育我Kearnighan&Pike在这里做什么?自1982年以来,shell实现的这一方面是否发生了变化?

编辑:这是本书的整个程序.

#!/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
Run Code Online (Sandbox Code Playgroud)

我理解程序正在做什么,以及如果"$ @"> $ new的退出状态为0,if条件将如何评估为true.我不明白为什么PATH没有赋值$ opath有问题的"if"行.

Rom*_*aka 5

shell执行的扩展

PATH=$opath echo $PATH
Run Code Online (Sandbox Code Playgroud)

是(按此顺序):

  1. 扩展$PATH到当前值
  2. 扩展$opath到它的价值
  3. echoPATH等于扩展的环境中执行命令$opath.

因此命令会看到修改后的值PATH,但赋值不会影响shell执行的扩展.

而且,即使后续命令也不会看到新值$opath,它仅限于当前命令.

当命令部分为空时(即只有一个赋值),该逻辑会改变;

PATH=$opath
echo $PATH
Run Code Online (Sandbox Code Playgroud)

将首先更改$PATH当前执行环境中的值,然后打印新值.