Решение
export GOPATH=~/mygo:~/go
export GOBIN=${(j<:>)${${(s<:>)GOPATH}/%//bin}}
Объяснение
Хотя любая программа, использующая GOPATH
, может интерпретировать его как массив, для zsh
это просто скаляр («строка»).
Чтобы добавить строку (/bin
) к каждому элементу, сначала нужно разбить строку «$ GOPATH» на массив.В zsh
это можно сделать с помощью флага расширения параметра s:string:
.Это разбивает скаляр на string
и возвращает массив.Вместо :
могут использоваться любые другие символы или соответствующие пары ()
, []
, {}
или <>
.В этом случае это должно быть сделано, потому что string
должно быть :
.
GOPATH_ARRAY=(${(s<:>)GOPATH)
Теперь расширение параметра ${name/pattern/repl}
можно использовать для добавления /bin
ккаждый элемент, или, скорее, заменить конец каждого элемента на /bin
.Чтобы соответствовать концу строки, 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
.
Лично я чувствую, что это немного "хакерски", в основном потому, что вам нужно написать /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"
- но я бы рекомендовал против него.~
в качестве синонима домашнего каталога не является функцией операционной системы, и хотя оболочки обычно поддерживают его, другие программы (те, кому требуется GOPATH
или GOBIN
) могут этого не делать.