बैश उर्फ की समस्या का सामान्यीकृत समाधान चाहने के लिए वैध तकनीकी कारण हैं, जिसमें मनमाना तर्क देने के लिए कोई तंत्र नहीं है। एक कारण यह है कि यदि आप जिस कमांड को निष्पादित करना चाहते हैं, वह पर्यावरण के उन परिवर्तनों से प्रतिकूल रूप से प्रभावित होगा जो किसी फ़ंक्शन को निष्पादित करने के परिणामस्वरूप होते हैं। अन्य सभी मामलों में, कार्यों का उपयोग किया जाना चाहिए।
हाल ही में मुझे इसके समाधान के लिए प्रयास करने के लिए मजबूर किया गया है कि मैं चर और कार्यों की परिभाषा को मुद्रित करने के लिए कुछ संक्षिप्त कमांड बनाना चाहता था। इसलिए मैंने उस उद्देश्य के लिए कुछ कार्य लिखे। हालांकि, कुछ चर हैं जो एक फ़ंक्शन कॉल द्वारा ही बदल दिए जाते हैं (या हो सकते हैं)। उनमें से हैं:
FUNCNAME BASH_SOURCE BASH_LINENO BASH_ARGC BASH_ARGV
वैरिएबल डिफेंस को प्रिंट करने के लिए मैं (एक फ़ंक्शन में) मूल कमांड का उपयोग कर रहा था। सेट कमांड द्वारा फॉर्म आउटपुट में था:
sv () { set | grep --color=never -- "^$1=.*"; }
उदाहरण के लिए:
> V=voodoo
sv V
V=voodoo
समस्या: यह ऊपर उल्लिखित चर की परिभाषाओं को मुद्रित नहीं करेगा क्योंकि वे वर्तमान संदर्भ में हैं , उदाहरण के लिए, यदि एक इंटरैक्टिव शेल प्रॉम्प्ट में (या किसी फ़ंक्शन कॉल में नहीं), FUNCNAME परिभाषित नहीं है। लेकिन मेरा कार्य मुझे गलत जानकारी बताता है:
> sv FUNCNAME
FUNCNAME=([0]="sv")
इस विषय पर अन्य पोस्ट में अन्य लोगों द्वारा उल्लिखित एक समाधान का उल्लेख किया गया है। इस विशेष कमांड के लिए वेरिएबल डिफेंस को प्रिंट करना। और जिसके लिए केवल एक तर्क की आवश्यकता है, मैंने यह किया:
alias asv='(grep -- "^$(cat -)=.*" <(set)) <<<'
जो सही आउटपुट (कोई नहीं) देता है, और परिणाम की स्थिति (झूठी):
> asv FUNCNAME
> echo $?
1
हालाँकि, मैं अभी भी एक समाधान खोजने के लिए मजबूर महसूस कर रहा था जो मनमानी संख्या के लिए काम करता है।
एक बैश अलियास कमांड के लिए मनमाना तर्क पारित करने के लिए एक सामान्य समाधान:
# (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".
उदाहरण के लिए:
> . 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
इस समाधान के बारे में एक अच्छी बात यह है कि ट्रैप्ड कमांड को कंपोज करते समय कमांड कमांड को काम करने के लिए इस्तेमाल किए जाने वाले सभी विशेष ट्रिक्स काम करेंगे। एकमात्र अंतर यह है कि सरणी सिंटैक्स का उपयोग किया जाना चाहिए।
उदाहरण के लिए,
यदि आप "$ @" चाहते हैं, तो "$ {CMD_ARGV [@]}" का उपयोग करें।
यदि आप "$ #" चाहते हैं, तो "$ {# CMD_ARGV [@]}" का उपयोग करें।
आदि।