令人困惑的外壳语法



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

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

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

PATH=/bin:/usr/bin

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

让我感到困惑的是,当我将那行改为

if PATH=$opath echo $PATH

标准是:

/

bin:/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

我了解程序在做什么,以及如果退出状态"$@">$new为 0,if 条件将如何计算为 true。我不明白的是为什么在有问题的"if"行中没有为 PATH 分配 $opath 的值。

shell 执行的扩展

PATH=$opath echo $PATH

是(按此顺序):

  1. $PATH展开为其当前值
  2. $opath扩展到其价值
  3. PATH等于$opath扩展的环境中执行 echo 命令。

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

此外,即使是后续命令也不会看到$opath的新值,它仅限于当前命令。

当命令部分为空时,此逻辑会发生变化(即只有一个赋值);

PATH=$opath
echo $PATH

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

最新更新