使用 zsh 5.8.1 (x86_64-apple-darwin21.0),我有一个依赖于zsh 默认从 1 开始的数组索引,并且我想确保任何以前的用户设置都不会干扰这一点。最好的做法似乎是存储用户的当前KSH_ARRAYS
设置,然后取消设置此选项,然后在完成后将该选项重置为其原始设置。我有以下内容:
#!/usr/bin/env zsh
if [[ -o ksharrays ]]; then
echo "setting ksharrays_is_set to 1...";
ksharrays_is_set=1;
else
echo "setting ksharrays_is_set to 0...";
ksharrays_is_set=0;
fi
unsetopt KSH_ARRAYS;
# here is where my script runs
if [[ ksharrays_is_set -eq 1 ]]; then
echo "setting the ksharrays option...";
setopt ksharrays;
fi
为了测试这一点,我setopt ksharrays
在终端中运行,然后运行我的脚本。但是,我仍然看到setting ksharrays_is_set to 0...
终端有回声。
当我添加setopt ksharrays
到第 2 行(直接在 shebang 下方)时,我看到了setting ksharrays_is_set to 1...
和setting the ksharrays option...
预期的一样。
为什么当我在终端中设置它时,该选项没有被选中,但当我在脚本中设置它时却被选中?
编辑:我还尝试添加setopt ksharrays
到我的~/.zshrc
和~/.zshenv
ingsource
这些文件,然后运行上面的脚本。这也导致了setting ksharrays_is_set to 0...
输出,而不是预期的输出。我setopt
通过在终端中运行不带参数的命令来确认该命令已生效:
$ setopt
combiningchars
interactive
ksharrays
login
monitor
promptsubst
shinstdin
zle
编辑2:我添加echo $(setopt)
到脚本的顶部。唯一打印出来的是nohashdirs
.当我直接在终端中不带参数运行时,我没有看到combiningchars
、interactive
或任何其他选项。setopt
答案1
当您从另一个程序运行一个程序时,每个程序都是它自己的东西。仅仅因为您从 zsh 运行 zsh 并不会使第二个 zsh 以某种方式从其父级继承某些设置。
您已经编写了一个 zsh 脚本。所以当你执行/path/to/your/script
,操作系统会发现该文件以舍邦行并zsh
从命令搜索路径运行。它并不关心谁启动了这个过程。 zsh 的新实例以默认设置启动。任何设置(例如 zsh 选项)的更改都必须来自某个地方,例如命令行或配置文件或脚本的内容。
当一个程序调用另一个程序时,某些设置会被继承,但它们是适用于所有程序的设置,而不仅仅是 zsh。主要是,环境变量是遗传的。 Zsh 不根据环境变量设置选项。
如果你使用的是.
或者source
内置的来自 zsh。这将指示 zsh 从文件中读取命令,就像它们已写入包含该.
命令的文件中一样。不幸的是,没有明确的术语来区分这两种情况:两者都称为“脚本”。脚本可以被执行(/path/to/script
从任何程序运行)或来源(. /path/to/script
从 zsh 运行);同一个文件可以以任何一种方式使用,但大多数脚本只能以一种方式使用。您的脚本是一个要执行的独立程序。
回到 zsh 开始运行正在执行的脚本时发生的情况:当 zsh 运行脚本时,它不会加载.zshrc
(仅适用于 zsh 交互运行时),但它会加载/etc/zshenv
和~/.zshenv
。如果您输入setopt ksh_arrays
,您的脚本将采用该设置。放入任何setopt
命令(或几乎任何命令).zshenv
都是一个糟糕的主意,会破坏脚本。
一旦你的脚本退出,没有人关心(甚至记住)它启用了哪些 zsh 选项。因此,如果您想启用ksh_arrays
脚本中的所有代码,只需setopt ksh_arrays
在脚本开头、故事结尾附近运行即可。
如果只有部分代码需要某些选项,则将该部分放入函数中并设置local_options
你的函数中的选项。例如,要ksh_arrays
在函数执行时启用并在退出时恢复默认设置,请将其放置setopt local_options ksh_array
在函数顶部附近。此外,如果更改了某些其他选项的默认值,则需要更改某些选项的代码通常也会中断。因此,当 zsh 代码需要在选项可能已从默认值更改的上下文中运行时,将该代码放入函数中并运行emulate -LR zsh
在那个函数中。这使得该函数使用默认选项运行,并且也local_options
启用,因此当函数退出时,对选项的任何更改都将被撤消。某些代码应遵循某些“最终用户”选项,例如mark_dirs
;对于此类代码,请使用emulate -L zsh
(即删除-R
)选项。例如,这对于完成功能来说是正确的。