1
votes

Assigner une commande à une variable dans Zsh

Je suis récemment passé à Zsh, et j'ai quelques fichiers de shell de configuration que je veux charger dans Zsh. Cependant, il ne semble pas que Zsh permette l'affectation de commandes par chaîne à une variable.

Ce qui fonctionnait

command not found: git config --global

Dans Bash, ce qui précède fonctionne très bien. Cependant dans Zsh il imprime:

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

Si j'écris simplement la commande entière dans le même fichier, cela fonctionne, mais si j'attribue une commande partielle à une variable, ce n'est pas le cas. Y a-t-il un moyen de contourner ceci?

Merci,

zsh

9 commentaires

Voyez si cela aide: stackoverflow.com/questions/13665172/...


@zedfoxus - c'est absolument le cas. Je viens de trouver ça aussi. J'ai demandé un peu tôt, le google ne me donnait pas les meilleurs résultats lorsque j'ai rencontré ce problème pour la première fois. Ce qui est bien, c'est que dans Zsh, je peux parcourir un tableau de chaînes pour attribuer ces configurations. Merci!


Maintenant, si cela fonctionne avec l'attribution de fonctions git: git config --global alias.coo '!f() { ... }' ce serait étonnant.


Très bien. Je suis sûr que vous trouverez un moyen de rendre votre flux de travail incroyable :)


@zedfoxus - absolument, je vais mettre à jour ceci avec une réponse pour les autres au cas où ils rencontreraient le mien avant l'autre. J'espère que votre flux de travail est incroyable! :)


N'utilisez pas la balise bash pour les questions zsh. (Un bon point de départ: l'expertise en bash est-elle nécessaire et suffisante pour qu'elle soit responsable?)


À propos, la meilleure pratique est de ne jamais utiliser de variables pour stocker des commandes même dans bash - utilisez plutôt des fonctions, comme décrit dans BashFAQ # 50 . La fonction équivalente à votre exemple serait git_conf() { git config --global "$@"; } , après quoi on peut exécuter git_conf rebase.autosquash true sur n'importe quel shell compatible POSIX (et certains non conformes comme zsh).


@CharlesDuffy "Eval is evil" est vrai, mais pas sûr à ce sujet dans le contexte bash. Néanmoins, j'aime l'approche des meilleures pratiques. Je mettrai à jour ma réponse pour refléter cela. Merci.


En ce qui concerne eval-is-evil-in-bash, voir BashFAQ # 48 . Il est certes possible de l'utiliser en toute sécurité, mais prend une certaine prudence.


3 Réponses :


1
votes

Cela a déjà été répondu. J'ai demandé un peu tôt avant ma due diligence avec le google. Je vais donc mettre ma réponse ci-dessous.

Solution

L'utilisation de la fonction eval fonctionnera. Mais ce n'est pas la meilleure pratique. Pour les meilleures pratiques, j'utilise une fonction shell.

Dans mon cas, j'ai beaucoup de configurations en double qui raccourcissent une partie de la frappe, donc ce n'est pas aussi verbeux. Dans ce cas, j'ai en outre opté pour un tableau associatif de configurations considérant que chaque configuration aura une clé unique.

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 "$@"
}


0 commentaires

2
votes

Vous voulez que le shell divise votre "commande" sur les espaces. Par conséquent, vous devez l'invoquer comme

${(z)git_conf} rebase.autosquash true

Bien sûr, il s'agit d'une mauvaise utilisation des variables du shell et fonctionne dans des cas aussi simples. Je me demande pourquoi vous voulez utiliser une variable shell ici, et non - disons - une fonction shell. Même l'utilisation d'une variable de tableau serait plus flexible.


1 commentaires

Dans la section des commentaires, on m'a dit qu'il était préférable d'utiliser une fonction shell. J'ai changé ma réponse pour refléter les meilleures pratiques.



0
votes

Vous pouvez également faire:

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


0 commentaires