Il existe des raisons techniques légitimes de vouloir une solution généralisée au problème de l'alias bash n'ayant pas de mécanisme pour prendre un repositionnement des arguments arbitraires. L'une des raisons est que la commande que vous souhaitez exécuter serait affectée par les modifications de l'environnement résultant de l'exécution d'une fonction. Dans tous les autres cas, les fonctions doivent être utilisées.
Ce qui m'a récemment poussé à essayer une solution, c'est que je voulais créer des commandes abrégées pour imprimer les définitions des variables et des fonctions. J'ai donc écrit quelques fonctions à cet effet. Cependant, certaines variables sont (ou peuvent être) modifiées par un appel de fonction lui-même. Parmi eux:
FUNCNAME BASH_SOURCE BASH_LINENO BASH_ARGC BASH_ARGV
La commande de base que j'utilisais (dans une fonction) pour imprimer des defns variables. sous la forme sortie par la commande set était:
sv () { set | grep --color=never -- "^$1=.*"; }
Par exemple:
> V=voodoo
sv V
V=voodoo
Problème: cela n'imprimera pas les définitions des variables mentionnées ci-dessus car elles sont dans le contexte actuel , par exemple, si dans une invite de shell interactive (ou pas dans les appels de fonction), FUNCNAME n'est pas défini. Mais ma fonction me dit la mauvaise information:
> sv FUNCNAME
FUNCNAME=([0]="sv")
Une solution que j'ai trouvée a été mentionnée par d'autres dans d'autres articles sur ce sujet. Pour cette commande spécifique pour imprimer les définitions de variables., Et qui ne nécessite qu'un seul argument, j'ai fait ceci:
alias asv='(grep -- "^$(cat -)=.*" <(set)) <<<'
Ce qui donne la sortie correcte (aucune) et l'état du résultat (faux):
> asv FUNCNAME
> echo $?
1
Cependant, je me sentais toujours obligé de trouver une solution qui fonctionne pour un nombre arbitraire d'arguments.
Une solution générale pour passer des arguments arbitraires à une commande alias Bash:
# (I put this code in a file "alias-arg.sh"):
# cmd [arg1 ...] – an experimental command that optionally takes args,
# which are printed as "cmd(arg1 ...)"
#
# Also sets global variable "CMD_DONE" to "true".
#
cmd () { echo "cmd($@)"; declare -g CMD_DONE=true; }
# Now set up an alias "ac2" that passes to cmd two arguments placed
# after the alias, but passes them to cmd with their order reversed:
#
# ac2 cmd_arg2 cmd_arg1 – calls "cmd" as: "cmd cmd_arg1 cmd_arg2"
#
alias ac2='
# Set up cmd to be execed after f() finishes:
#
trap '\''cmd "${CMD_ARGV[1]}" "${CMD_ARGV[0]}"'\'' SIGUSR1;
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# (^This is the actually execed command^)
#
# f [arg0 arg1 ...] – acquires args and sets up trap to run cmd:
f () {
declare -ag CMD_ARGV=("$@"); # array to give args to cmd
kill -SIGUSR1 $$; # this causes cmd to be run
trap SIGUSR1; # unset the trap for SIGUSR1
unset CMD_ARGV; # clean up env...
unset f; # incl. this function!
};
f' # Finally, exec f, which will receive the args following "ac2".
Par exemple:
> . alias-arg.sh
> ac2 one two
cmd(two one)
>
> # Check to see that command run via trap affects this environment:
> asv CMD_DONE
CMD_DONE=true
Une bonne chose à propos de cette solution est que toutes les astuces spéciales utilisées pour gérer les paramètres de position (arguments) des commandes fonctionneront lors de la composition de la commande capturée. La seule différence est que la syntaxe du tableau doit être utilisée.
Par exemple,
Si vous voulez "$ @", utilisez "$ {CMD_ARGV [@]}".
Si vous voulez "$ #", utilisez "$ {# CMD_ARGV [@]}".
Etc.