考虑一下这一点。IFS
仅在执行时设置read
。
IFS='' read -r REPLY
但是,如果我做类似的事情.
(来源),即使在执行该行代码之后,变量也会被分配和更改。
PATH="/new_path:${PATH}" . script.sh
echo "$PATH" # Value changed
为什么会出现这种情况呢?我认为.
和 Bash 一样source
,是一个类似于read
or 的命令echo
。有没有任何文档,例如2.14.特殊的内置实用程序,提到这种行为?
如何以符合 POSIX 的方式临时设置$PATH
和.
(源)文件?
答案1
.
是一个特别的内置。
根据 POSIX:
2. 如简单命令中所述,调用特殊内置实用程序之前的变量赋值在内置实用程序完成后仍然有效;常规内置实用程序或其他实用程序不会出现这种情况。
该特定要求 bash 仅在 POSIX 模式下满足,例如调用 as 时sh
(更一般地,当posix
启用其选项时)。
要删除他们的特殊性到一个特别的内置的,在 POSIX 兼容的 shell 中,您可以使用command
as 作为前缀command
本身是一个普通的内置函数,而不是特别的一。 POSIX 明确提到:
如果 command_name 与特殊内置实用程序之一的名称相同,则特殊内置实用程序开头的枚举列表中的特殊属性将不会出现。在所有其他方面,如果 command_name 不是函数的名称,则命令(不带选项)的效果应与省略命令相同。
bash-5.1$ echo printenv PATH > file
bash-5.1$ (PATH=/; PATH=/usr/bin . ./file; echo "$PATH")
/usr/bin
/
bash-5.1$ set -o posix
bash-5.1$ (PATH=/; PATH=/usr/bin . ./file; echo "$PATH")
/usr/bin
/usr/bin
bash-5.1$ (PATH=/; PATH=/usr/bin command . ./file; echo "$PATH")
/usr/bin
/
对于特殊的内置函数,例如eval
或.
,这是 POSIX 的一个疏忽,因为尊重这些内置函数意味着为了能够$var
在var=value command . file
或后恢复var=value command eval some-code
,shell 必须实现某种类型的变量堆栈和变量的有效局部范围,POSIX 没有另外指定。您会发现,在实践中,它并不适用于所有sh
实现,特别是 POSIX 规范所基于的 ksh88。
答案2
如何以 POSIX 兼容的方式临时设置
$PATH
和.
(源)文件?
OPATH=$PATH PATH=...
. someSource
PATH=$OPATH
答案3
请注意,此答案仅适用于 bash。它不适用于完全符合 POSIX 标准的 shell。
难道不可能在一篇声明中完成吗?
是的!将其包装在一个函数中。这种方法不需要额外的变量(保持变量污染最小)。
源文件:
$ cat script.sh
echo "in script.sh file"
var='altered'
采购文件:
$ cat test.sh
#!/bin/bash
var='original'
echo $PATH
echo
_() { . "$1" ; }
PATH="/tmp:${PATH}" _ script.sh
echo
echo $PATH
echo
echo "$var"
echo
源文件中的语句和变量$var
用于验证文件script.sh
是否成功获取。
更改$PATH
仅在函数内有效_
(您可以使用更好的名称)。$PATH
声明后不改变。