我有一个文件,它来自.bashrc
并.zshrc
包含一些功能。它以前是两个单独的文件(对于每个 shell),但我现在使用一个文件,因为这些文件几乎相同,而且我更容易管理一个函数文件。
这两个 shell 有一个不同的函数,所以我想我可以使用条件语句以便使用正确的语句:
[[ $BASH_VERSION ]] && shell=bash
[[ $ZSH_VERSION ]] && shell=zsh
# Search man page for string
if [[ $shell == bash ]]; then
mans() {
local q="\'"
local q_pattern="'${1//$q/$q\\$q$q}'"
local MANPAGER="less -+MFX -p $q_pattern"
man "$2"
}
elif [[ $shell == zsh ]]; then
mans() MANPAGER="less -+MFX -p ${(q+)1}" man $2
fi
这在 zsh 中似乎工作正常,但是当切换到 bash 时,我从 zsh 行收到错误,即使它不应该在 bash 中使用。有什么办法可以阻止它解析该行吗?
您可以定义一些
ifbash
,ifzsh
,endif
别名,例如::||:<<"MARKER"
...MARKER
是注释一段代码的惯用方式。这就像在 stdin 上:<<"MARKER"
运行:
带有 here-doc 的 noop 内置函数,但是有了额外的:||
,第二个:
不会运行,甚至不会创建 here-document,只是被解析掉了。请注意,
endif
不能缩进,也不能跟任何东西;它必须构成整条线。ifbash
/ifzsh
s 不能嵌套(并不是说在这里无论如何都有意义)。顺便说一句,
man
似乎自己在环境变量中进行引号解析MANPAGER
(而不是调用 shell,更不用说你的了$SHELL
)并且似乎不支持$'...'
引号的形式,因此使用q+
可能使用该形式的参数扩展标志某些字符串的引号不正确。改用qq
它使用单引号(\'
在引号外以转义单引号¹),就像您的 bash 版本一样。¹ 除非
rcquotes
启用该选项,否则将使用''
à la 。rc
在函数的开头添加emulate -L zsh
,以在该函数中拥有一组健全的本地选项无济于事,因为需要在定义函数时禁用该选项,而不是运行。Bash 仍然需要解析整个文件,即使它不会执行每一行。您通常不能隐藏条件后面的语法错误,只能隐藏运行时错误。
在你的位置,我会回到使用 separate
.zshrc
and.bashrc
。然后我会把通用函数放在第三个文件中(确保这个文件只使用与两者兼容的语法)并.zshrc
从.bashrc
.在我看来,这是世界上最好的:
.zshrc
它们永远不会被 bash 读取的地方。同样,只有 bash 的东西存在于.bashrc
.任何 shell 都必须解析条件中的代码以找到条件结束的部分,即使没有其他原因也是如此。
除了将特定于 shell 的代码放在另一个文件或字符串中之外
eval
,您还可以使用 here-doc 来隐藏它并source
直接使用 here-doc。与 using 几乎相同eval
,但 here-doc 的优点是其中的代码可以同时包含单引号和双引号,而不会出现任何烦人的转义问题。例如,此脚本说明
hello, 'bar', I'm zsh
如果使用 zsh 运行,并在 Bash 中抛出错误:不过,我不确定是否
source /dev/stdin
适用于所有 shell 和系统。(是的,source
是内置命令的非标准名称.
,但它应该在 Bash 和 zsh 中工作,而且无论如何该命令只需要存在于运行条件内部的 shell 中。)其他人已经指出了为什么 bash 在句法上解析条件的内容
$shell == zsh
。在 zsh 上你可以使用
而这不是合法的 bash 语法(函数需要 {})。
但是,在 zsh 上,您还可以对函数使用 POSIX 语法,这将使两个 shell 都满意:
此外,我通常会将它们更改
[[
为单一语法,这样如果在不支持的[
其他 shell(例如 )上运行,文件就不会中断:dash
[[
@ilkkachu 建议的方法有效: