zsh-为什么我的脚本没有读取我的选项设置?

zsh-为什么我的脚本没有读取我的选项设置?

使用 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~/.zshenvingsource这些文件,然后运行上面的脚本。这也导致了setting ksharrays_is_set to 0...输出,而不是预期的输出。我setopt通过在终端中运行不带参数的命令来确认该命令已生效:

$ setopt

combiningchars
interactive
ksharrays
login
monitor
promptsubst
shinstdin
zle

编辑2:我添加echo $(setopt)到脚本的顶部。唯一打印出来的是nohashdirs.当我直接在终端中不带参数运行时,我没有看到combiningcharsinteractive或任何其他选项。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)选项。例如,这对于完成功能来说是正确的。

相关内容