Назначение команды переменной в Zsh

#zsh

#zsh

Вопрос:

Недавно я перешел на Zsh, и у меня есть несколько файлов оболочки конфигурации, которые я хочу загрузить в Zsh. Однако, похоже, что Zsh не позволяет присваивать команду переменной по строке.

Что раньше работало

 local git_conf='git config --global'
$git_conf rebase.autosquash true
  

В Bash вышеуказанное работает нормально. Однако в Zsh он выводит:

 command not found: git config --global
  

Если я просто запишу всю команду в тот же файл, это сработает, но если я назначу частичную команду переменной, это не сработает. Есть ли способ обойти это?

Спасибо,

Комментарии:

1. @zedfox — это абсолютно так. Я только что нашел это тоже. Я спросил немного раньше, Google не давал мне лучших результатов, когда я впервые столкнулся с этой проблемой. Что приятно, так это то, что в Zsh я могу перебирать массив строк, чтобы назначить эти конфигурации. Спасибо!

2. Теперь, если это работает с назначением функций git: git config --global alias.coo '!f() { ... }' это было бы потрясающе.

3. Отличная работа. Я уверен, что вы найдете способ сделать свой рабочий процесс потрясающим 🙂

4. @zedfox — безусловно, я обновлю это ответом для других на случай, если они столкнутся с моим первым перед другим. Надеюсь, ваш рабочий процесс потрясающий! 🙂

5. Что касается eval-is-evil-in-bash, см. BashFAQ #48 . Это, конечно , можно использовать безопасно, но требует некоторой осторожности.

Ответ №1:

Вы хотите, чтобы оболочка разделила вашу «команду» на пробелы. Следовательно, вы должны вызвать ее как

 ${(z)git_conf} rebase.autosquash true
  

Конечно, это неправильное использование переменных оболочки и работает в таких простых случаях. Интересно, почему вы хотите использовать здесь переменную оболочки, а не, скажем, функцию оболочки. Даже использование переменной массива было бы более гибким.

Комментарии:

1. В разделе комментариев мне было сказано, что лучше всего использовать функцию оболочки. Я изменил свой ответ, чтобы отразить наилучшую практику.

2. Ну, не используйте грузовик, если вы также можете перевозить свое вино на велосипеде. Конечно, мы стараемся избегать использования расширения параметров для расширения до полной команды (включая параметры), но ваш первоначальный вопрос верен, поскольку бывают случаи, когда действительно функция не может продвинуть вас дальше. На самом деле, если вы зайдете так далеко, что вместо этого будете использовать функцию, вы также можете сделать ее еще более гибкой, если сможете превратить ее в отдельный скрипт. Функция может быть выполнена только из процесса zsh, который ее определяет, в то время как скрипт может быть запущен отовсюду.

Ответ №2:

Вы также можете сделать:

 local git_conf=(git config --global)
"$git_conf[@]" rebase.autosquash true
  

Ответ №3:

На самом деле на этот вопрос уже был дан ответ. Я спросил немного раньше, чем моя должная осмотрительность с Google. Итак, я приведу свой ответ ниже.

Решение

Использование eval функции будет работать. Но это не лучшая практика. Для лучшей практики я использую функцию оболочки.

В моем случае у меня много повторяющихся конфигураций, которые сокращают часть ввода, поэтому они не такие подробные. В этом случае я дополнительно выбрал ассоциативный массив конфигураций, учитывая, что каждая конфигурация будет иметь уникальный ключ.

 declare -A confs
confs=(
    rebase.autosquash true
    alias.a '!ga() {
        if [ $# -eq 0 ]; then
            git add .
        else
            git add "$@"
        fi
    }; ga'
)

for key value in ${(kv)confs}
do
  # this works, however I'd like to stay away from eval whenever possible
  # command="specific command that's always the same ${key} ${value}"
  # eval ${command}

  # best practice
  git_config ${key} ${value}
done

git_config() {
    git config --global "$@"
}