Keyfî argümanları yeniden konumlandırmak için bir mekanizmaya sahip olmayan bash takma adı sorununa genel bir çözüm istemenin meşru teknik nedenleri vardır. Bunun bir nedeni, yürütmek istediğiniz komutun, bir işlev yürütmekten kaynaklanan ortamdaki değişikliklerden olumsuz etkilenmesi. Toplamda diğer durumlarda, fonksiyonlar kullanılmalıdır.
Son zamanlarda beni buna bir çözüm denemeye zorlayan şey, değişkenlerin ve fonksiyonların tanımlarını yazdırmak için bazı kısaltılmış komutlar oluşturmak istememdi. Bu yüzden bu amaçla bazı fonksiyonlar yazdım. Ancak, bir işlev çağrısının kendisi tarafından değiştirilen (veya değiştirilebilen) bazı değişkenler vardır. Aralarında:
FUNCNAME BASH_SOURCE BASH_LINENO BASH_ARGC BASH_ARGV
Değişken hatalarını yazdırmak için (işlevde) kullandığım temel komut. set komutunun çıktı formunda:
sv () { set | grep --color=never -- "^$1=.*"; }
Örneğin:
> V=voodoo
sv V
V=voodoo
Sorun: Bu, yukarıda belirtilen değişkenlerin tanımlarını geçerli bağlamda oldukları gibi yazdırmaz , örneğin, etkileşimli bir kabuk isteminde (veya herhangi bir işlev çağrısında bulunmuyorsa), FUNCNAME tanımlanmamıştır. Ama işlevim bana yanlış bilgiyi söylüyor:
> sv FUNCNAME
FUNCNAME=([0]="sv")
Geldiğim bir çözüm, bu konudaki diğer yayınlarda başkaları tarafından belirtildi. Değişken hatalarını yazdırmak için bu özel komut ve yalnızca bir bağımsız değişken gerektirir, bunu yaptım:
alias asv='(grep -- "^$(cat -)=.*" <(set)) <<<'
Bu da doğru çıktıyı (yok) ve sonuç durumunu (yanlış) verir:
> asv FUNCNAME
> echo $?
1
Ancak, yine de rastgele sayıda argüman için çalışan bir çözüm bulmaya zorlandım.
Bash Takma Adlı Komuta Keyfi Argüman Aktarmaya Genel Bir Çözüm:
# (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".
Örneğin:
> . 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
Bu çözümle ilgili güzel bir şey, konumsal parametreleri (argümanları) komutlara işlemek için kullanılan tüm özel hilelerin, yakalanan komutu oluştururken işe yaramasıdır. Tek fark, dizi sözdiziminin kullanılması gerektiğidir.
Örneğin,
"$ @" İstiyorsanız, "$ {CMD_ARGV [@]}" kullanın.
"$ #" İstiyorsanız, "$ {# CMD_ARGV [@]}" kullanın.
Vb.