Ada alasan teknis yang sah untuk menginginkan solusi umum untuk masalah bash alias tidak memiliki mekanisme untuk mengambil reposisi argumen sewenang-wenang. Salah satu alasannya adalah jika perintah yang ingin Anda jalankan akan terpengaruh oleh perubahan lingkungan yang dihasilkan dari menjalankan fungsi. Dalam semua kasus lain , fungsi harus digunakan.
Apa yang baru-baru ini memaksa saya untuk mencoba solusi untuk ini adalah bahwa saya ingin membuat beberapa perintah singkat untuk mencetak definisi variabel dan fungsi. Jadi saya menulis beberapa fungsi untuk tujuan itu. Namun, ada variabel tertentu yang (atau mungkin) diubah oleh pemanggilan fungsi itu sendiri. Diantaranya adalah:
FUNCNAME BASH_SOURCE BASH_LINENO BASH_ARGC BASH_ARGV
Perintah dasar yang saya gunakan (dalam suatu fungsi) untuk mencetak variabel defns. dalam bentuk output oleh perintah set adalah:
sv () { set | grep --color=never -- "^$1=.*"; }
Misalnya:
> V=voodoo
sv V
V=voodoo
Masalah: Ini tidak akan mencetak definisi variabel yang disebutkan di atas karena mereka berada dalam konteks saat ini , misalnya, jika dalam prompt shell interaktif (atau tidak dalam panggilan fungsi apa pun), FUNCNAME tidak didefinisikan. Tetapi fungsi saya memberi tahu saya informasi yang salah:
> sv FUNCNAME
FUNCNAME=([0]="sv")
Salah satu solusi yang saya temukan telah disebutkan oleh orang lain di posting lain tentang topik ini. Untuk perintah khusus ini untuk mencetak variabel, dan yang hanya membutuhkan satu argumen, saya melakukan ini:
alias asv='(grep -- "^$(cat -)=.*" <(set)) <<<'
Yang memberikan output yang benar (tidak ada), dan status hasil (salah):
> asv FUNCNAME
> echo $?
1
Namun, saya masih merasa harus menemukan solusi yang berfungsi untuk sejumlah argumen yang berubah-ubah.
Solusi Umum Untuk Melewati Argumen Sewenang-wenang Pada Perintah Bash Alias:
# (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".
Misalnya:
> . 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
Satu hal yang menyenangkan tentang solusi ini adalah bahwa semua trik khusus yang digunakan untuk menangani parameter posisi (argumen) untuk perintah akan bekerja ketika menyusun perintah yang terperangkap. Satu-satunya perbedaan adalah sintaks array harus digunakan.
Misalnya,
Jika Anda ingin "$ @", gunakan "$ {CMD_ARGV [@]}".
Jika Anda ingin "$ #", gunakan "$ {# CMD_ARGV [@]}".
Dll