【问题标题】:zshrc doesn't recognize custom bash functionszshrc 无法识别自定义 bash 函数
【发布时间】:2021-01-21 01:51:14
【问题描述】:

我最近从 bash 迁移到 zsh,和大多数人一样,我有我的自定义 bash 别名/函数来简化 git 和 env 采购操作。特别是其中有 2 个在 zsh 上运行时无法正常工作,但在 bash 上却完全正常。

export REPO_ROOT=/home/pablo/repos/my_repo
alias croot='cd $REPO_ROOT'
alias subroot='cd $REPO_ROOT/subrepo/subrepo_1/'

repcheckout(){
 git checkout "$1"
 if [ $(pwd) == $REPO_ROOT ];  then
   subroot
 else
   croot
 fi
 git checkout "$1"
 if [ $(pwd) == $REPO_ROOT ];  then
   subroot
 else
   croot
 fi
}

我的想法是我有一组 main_repo-submodule 分支,当我签出主仓库时,我想签出相应分支中的子模块,而不是这样做:

$ git submodule update --init --recursive subrepo/subrepo_1

它检查了子模块中的正确提交,但没有更新我切换到某个本地分支。

对于之前的func,zsh在运行时抛出的错误

$ repcheckout my_cool_branch

M       subrepo/subrepo_1/
Switched to branch 'my_cool_branch'
repcheckout:2: = not found

后来我有一个 setup.sh 文件,我获取它的来源如下:

add2path() {
    if ! echo ${!1} | egrep "(^|:)$2(:|\$)" > /dev/null ; then
    declare -g $1="${!1}:$2"
    export "$1"
    fi
}

# GENERATED BINARY A
export BIN_A_HOME="$REPO_ROOT/bin_a"
add2path PATH "$BIN_A_HOME/bin"

与使用相同的 add2path 添加到 PYTHONPATH 的一些生成的 python 模块相同

哪个会导致错误:

add2path:1: bad substitution 

【问题讨论】:

  • 您可以将条件重写为[[ $PWD == $REPO_ROOT ]]。无需创建仅用于检查工作目录的子进程。使用[[ ... ]] 还允许您使用== 运算符。顺便说一句,${!1} 在 zsh 中也不起作用。一般来说,盲目地在另一种语言下运行为一种语言编写的代码是没有意义的,即使这些语言有相似之处。

标签: bash git zsh


【解决方案1】:

这两个函数都使用在 zsh 中无效的 bashism。

repcheckout 中,问题在于在[ ] 测试中使用== 运算符——标准运算符是=,但bash 允许== 作为同义词; zsh 没有。我还建议对两个字符串进行双引号以避免路径中出现奇怪字符的问题(并且可能使用"$PWD" 而不是$(pwd)):

if [ "$PWD" = "$REPO_ROOT" ];  then

add2path 中,问题在于echodeclare 命令中的间接变量引用${!1}。 zsh 也允许间接变量引用,但它的语法完全不同:${(P)1}。你可能可以用eval 制作一个交叉兼容的版本,但是如果你没有正确使用它,这往往会导致奇怪的错误;我只是根据 zsh 的需要重写函数。

编辑:如果您想在 bash 和 zsh 下使用相同的代码,eval 可能比尝试检测您所在的 shell 并使用基于此的条件代码更好。下面是编写跨 shell 兼容版本的快速尝试:

if ! eval "echo \"\$$1\"" | egrep "(^|:)$2(:|\$)" > /dev/null ; then
    eval "declare -g $1=\"\$$1:\$2\""
    export "$1"
    ...

引用很难看,但只要$1 包含有效标识符,它应该可以正常工作;如果没有,常见的eval 问题可能会抬头。

【讨论】:

  • 我的印象是 Zsh 不需要修复引用,但它确实改进了 Bash 代码。
  • 那么如何在脚本中检测它是从哪里调用的,从 bash 或 zsh 到使用一个版本的函数还是另一个?或者那是不可能的
  • repcheckout 现在就像一个魅力,谢谢。我会看看我能用 add2path 做什么
  • @tripleee 就像zsh 中的所有内容一样,参数扩展是否受分词影响是可配置的。虽然 default 是不执行分词,但我不会编写依赖于特定设置的代码。 (另外,[[ ... ]] 可以使它成为一个有争议的问题。)
  • @picatostas 我添加了一种使用eval 的方法,它应该适用于 bash 和 zsh。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-21
  • 1970-01-01
  • 2019-08-27
  • 2016-01-30
  • 2012-08-04
相关资源
最近更新 更多