我的登录 shell 是 zsh。我在文件中添加了以下两行.zprofile
:
path+=$HOME/foobar123
alias foo='echo bar'
bash
然后,如果我通过键入或fish
并按回车键切换到 bash 或 fish ,echo $PATH
将继续显示该foobar123
部分,但foo
别名不起作用。
这是为什么?为什么别名和路径修改的处理方式不同?
我的登录 shell 是 zsh。我在文件中添加了以下两行.zprofile
:
path+=$HOME/foobar123
alias foo='echo bar'
bash
然后,如果我通过键入或fish
并按回车键切换到 bash 或 fish ,echo $PATH
将继续显示该foobar123
部分,但foo
别名不起作用。
这是为什么?为什么别名和路径修改的处理方式不同?
path
是与 shell 变量绑定的 shell 数组变量,PATH
而 shell 变量本身又与环境变量绑定PATH
。当执行命令时,进程的所有内存都会被清除。
环境变量是一种在执行过程中传递数据的方法。与命令参数一样,它们是以 NUL 分隔的字符串列表,但与参数相反,按照惯例:
VAR=values
putenv()
、setenv()
、unsetenv()
、environ
变量)来维护记住的环境变量列表(环境),并执行命令,传递该列表(execl()
、execvp()
... 它们是execve()
系统调用的包装器)。具体来说,Shell 除了这样做之外,还会用其语言为它们收到的一些环境变量创建一个变量,并且其名称与 shell 变量的名称兼容。类似 Bourne 的 Shell 可以使用
export
内置命令将 shell 变量提升为环境变量(其他 shell 有等效变量)。csh、tcsh、zsh、yash、fish shell 有方法将
$PATH
或其他具有:
-分隔值的变量(通常是环境变量,例如PATH
)绑定到数组变量。为了进行比较,perl(也是一种编程语言解释器,但不是 shell 解释器)将环境变量映射到它的
%ENV
关联数组(例如,PATH
环境变量在中可用$ENV{PATH}
),awk
与 相同ENVIRON["PATH"]
,对于环境变量vim
有,$var
而它只是var
用于它自己的变量或@x
寄存器等。总而言之,环境变量
PATH
是通用的,可以被所有事物理解,并且可以(按照惯例)在执行过程中继承。没有与 shell 别名等效的功能,这是最初来自 csh 的一些(并非全部)shell 的(糟糕)特性,其语法因 shell 而异,任何语言的其他数据结构也各不相同。
某些 shell(例如
rc
和 派生函数 或 )bash
可以导出自己的函数(以及rc
和 派生函数中的数组),为此,它们会劫持环境变量,其中函数定义以特定格式存储,但只有同一 shell 的其他实例才能从环境中加载这些变量并重新创建它们编码的函数(或数组)。这些变量对于语法不同的其他 shell(或perl
、vim
、 ...)毫无意义。awk
为了能够将您的 zsh 别名列表传递给以便
bash
创建等效的 bash 别名,您需要使用该语言创建代码bash
,一旦评估该代码就会重新创建这些别名。bash
并且zsh
有一些共同的语法,特别是基本alias
内置语法是从 Korn shell 而不是 csh 复制而来的,但是 zsh 添加了更多功能,例如全局别名或后缀别名,并且在别名方面没有与 bash 相同的限制,并且 bash 的名称和值中都不能包含 NUL,因此并非所有 zsh 别名都可以转换为 bash 别名。尽管这两个 shell 以相同的方式理解单引号(只要
rcquotes
在 中未启用zsh
),但它们的引用语法也不同。zsh 在特殊关联数组中提供其普通别名列表$aliases
,并且 likebash
可以使用 转储别名定义列表alias -L
。但在后者中,它并不总是使用单引号,并且可能会转储名称或值在 bash 中不起作用的别名,因此您最好循环
$aliases
,过滤掉那些不能工作的别名bash
,然后手动进行引用(就像使用qq
参数扩展标志一样)。