在 .zshrc 配置中使用 var multi GOPATH 设置 GOBIN 根目录

GOBIN root setting with var multi GOPATH in .zshrc config

export GOPATH=~/mygo:~/go
export GOBIN=$GOPATH/bin

我希望 $GOBIN 等于 ~/mygo/bin:~/go/bin,但它是 ~/mygo:~/go/bin。 我怎样才能更好地设置它们?谢谢

解决方案

export GOPATH=~/mygo:~/go
export GOBIN=${(j<:>)${${(s<:>)GOPATH}/%//bin}}

说明

尽管任何使用 GOPATH 的程序都可能将其解释为数组,但对于 zsh 它只是一个标量 ("string")。

为了将字符串 (/bin) 附加到每个元素,首先需要将字符串“$GOPATH”拆分为一个数组。在 zsh 中,这可以通过 参数扩展标志 s:string: 来完成。这会在 string 和 returns 数组上拆分一个标量。可以使用任何其他字符或 ()[]{}<> 来代替 :。在这种情况下,必须这样做,因为 string:.

GOPATH_ARRAY=(${(s<:>)GOPATH)

现在 ${name/pattern/repl} 参数扩展 可用于将 /bin 附加到每个元素,或者更确切地说用 [= 替换每个元素的末尾19=]。为了匹配字符串的结尾,pattern 需要以 % 开头。由于应匹配任何字符串,否则该模式为空:

GOBIN_ARRAY=(${GOPATH_ARRAY/%//bin})

最后,数组需要转换回冒号分隔的字符串。这可以通过 j:string: 参数扩展标志 来完成。它对应于 s:string::

GOBIN=${(j<:>)GOBIN_ARRAY}

幸运的是,zsh 允许 嵌套替换,因此这可以在一条语句中完成,无需中间变量:

GOBIN=${(j<:>)${${(s<:>)GOPATH}/%//bin}}

备选方案

也可以在没有 参数扩展标志 嵌套替换 的情况下执行此操作,只需在末尾附加 /bin的字符串,另外用 /bin::

替换每个 :
export GOBIN=${GOPATH//://bin:}/bin

${name//pattern/repl} 扩展将 pattern 的每次出现替换为 repl 而不是像 ${name/pattern/repl}.

这也适用于 bash

个人感觉有点"hackish",主要是需要写两遍/bin,也完全避开了底层语义。但这只是个人喜好,结果都是一样的。


注:

像您在问题中所做的那样定义 GOPATH

export GOPATH=~/mygo:~/go

zsh 将使用您的主目录展开每个出现的 ~/。所以 GOPATH 的值将是 /home/kevin/mygo:/home/kevin/go - 假设用户名是 "kevin"。因此,GOBIN 也将具有扩展路径 /home/kevin/mygo/bin:/home/kevin/go/bin,而不是 ~/mygo/bin:~/go/bin

这可以通过引用值 GOPATH="~/mygo:~/go" 来避免,但我建议不要这样做。 ~ 作为主目录的同义词不是操作系统的特性,虽然 shell 通常支持它,但其他程序(那些需要 GOPATHGOBIN 的程序)可能不会这样做。