उद्धृत मापदंडों को प्राप्त करने और पुनर्प्राप्त करने के लिए बैश स्क्रिप्ट


98

मैं बश स्क्रिप्ट के उद्धृत मापदंडों को सुरक्षित रूप से नेस्टेड स्क्रिप्ट द्वारा प्राप्त करने का प्रयास कर रहा हूं। कोई विचार?

test.sh

#!/bin/bash
echo $*
bash myecho.sh $*

myecho.sh

#!/bin/bash
 echo $1
 echo $2
 echo $3
 echo $4

नमूना:

bash test.sh aaa bbb '"ccc ddd"'

परिणाम:

aaa bbb "ccc ddd"
aaa
bbb
"ccc
ddd"

परिणाम चाहता था

aaa bbb "ccc ddd"
aaa
bbb
ccc ddd

2
मैं बस उस सवाल को पूछने वाला था! अच्छा समय।
स्कॉटी टी

जवाबों:


70
#!/bin/bash
echo $*
bash myecho.sh "$@"

ध्यान दें "$ @" निर्माण विशिष्ट नहीं है और किसी भी POSIX शेल के साथ काम करना चाहिए (यह कम से कम डैश के साथ करता है)। यह भी ध्यान दें कि आपको जो आउटपुट चाहिए, वह आपको उद्धृत करने के अतिरिक्त स्तर की आवश्यकता नहीं है। IE बस उपरोक्त स्क्रिप्ट की तरह कहते हैं:

./test.sh 1 2 "3 4"

5
"$ @" कॉर्न और बैश सहित किसी भी बॉर्न शेल या बॉर्न शेल व्युत्पन्न (1978 के बाद से) के साथ काम करता है। संभवतः 95% समय, "$ @" का उपयोग करना सही है और $ * गलत है।
जोनाथन लेफ्लर

अच्छा! लेकिन, किसी को पता है कि क्या इसे स्टोर करने का कोई तरीका है "जैसा कि" एक चर में है? मूल $@एक फ़ंक्शन के अंदर उपलब्ध नहीं है (क्योंकि यह फ़ंक्शन तर्कों द्वारा अधिलेखित है)। मैंने कोशिश की foovar="$@"और foovar=$@+ "$foovar"फंक्शन में और किसी ने काम नहीं किया: - /
bitifet

143

आप एक सबस्क्रिप्ट में पैरामीटर पास करने के लिए "$ @" (उद्धृत डॉलर) का उपयोग करना चाहते हैं। इस तरह ....

ls-color.sh:

#!/bin/bash
/bin/ls --color=auto "$@"    # passes though all CLI-args to 'ls'


लेकिन क्यों.....

से बैश आदमी पेज :

$*- एक से शुरू होने वाले स्थितीय मापदंडों का विस्तार। जब विस्तार दोहरे उद्धरण चिह्नों के भीतर होता है, तो यह IFS विशेष चर के पहले वर्ण द्वारा अलग किए गए प्रत्येक पैरामीटर के मूल्य के साथ एक शब्द तक फैलता है। यह है, "$*"के बराबर है "$1c$2c...", जहां सी IFS चर के मूल्य का पहला चरित्र है। यदि IFS परेशान है, तो पैरामीटर रिक्त स्थान से अलग हो जाते हैं। यदि IFS शून्य है, तो पैरामीटर बिना विभाजक के हस्तक्षेप के जुड़ जाते हैं।

$@- एक से शुरू होने वाली स्थितिगत मापदंडों का विस्तार। जब विस्तार दोहरे उद्धरण चिह्नों के भीतर होता है, तो प्रत्येक पैरामीटर एक अलग शब्द में फैलता है। यह "$@"समतुल्य है, "$1" "$2" ...यदि एक शब्द के भीतर डबल-कोटेड विस्तार होता है, तो पहले पैरामीटर का विस्तार मूल शब्द के शुरुआती भाग के साथ जुड़ जाता है, और अंतिम पैरामीटर का विस्तार मूल के अंतिम भाग के साथ जुड़ जाता है शब्द। जब कोई स्थितिगत पैरामीटर नहीं होते हैं, "$@"और $@कुछ भी नहीं करने के लिए विस्तार करते हैं (यानी, उन्हें हटा दिया जाता है)।


कुछ डेमो स्क्रिप्ट सेट करना ...

echo 'echo -e "\$1=$1\n\$2=$2\n\$3=$3\n\$4=$4"' > echo-params.sh
echo './echo-params.sh $*' > dollar-star.sh
echo './echo-params.sh $@' > dollar-at.sh
echo './echo-params.sh "$*"' > quoted-dollar-star.sh
echo './echo-params.sh "$@"' > quoted-dollar-at.sh
chmod +x *.sh

"$@"- उद्धृत-डॉलर-एट एक सब -रील के लिए फिर से गुजरने के लिए एक पहचान परिवर्तन है (~ 99% समय, यह वही है जो आप करना चाहते हैं):

./quoted-dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2=            
  # $3= 'cc cc'
  # $4= "ddd ddd"

"$*"- उद्धृत-डॉलर-स्टार एक ही तार में आघात देता है (~ 1% समय जब आप वास्तव में यह व्यवहार चाहते हैं, उदाहरण के लिए एक सशर्त में:) if [[ -z "$*" ]]; then ...:

./quoted-dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa  'cc cc' "ddd ddd"   
  # $2=                     
  # $3=             
  # $4=

$*/ $@- उद्धरण के बिना, दोनों रूपों में एक स्तर के उद्धरण बंद हो जाते हैं और अंतर्निहित तारों से रिक्त स्थान की व्याख्या करते हैं लेकिन उद्धरण वर्णों को अनदेखा करते हैं (लगभग हमेशा, यह एक गलती है):

./dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc                  
  # $3= cc'
  # $4= "ddd

./dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc
  # $3= cc'
  # $4= "ddd

यदि आप कुछ मज़ा लेना चाहते हैं, तो आप "$ @" का उपयोग चीजों को घोंसले के लिए उतना ही गहरा कर सकते हैं जितना आप चाहते हैं, और यदि आप चाहें तो ढेरों से अलग तत्वों को धक्का दे सकते हैं।

function identity() {
  "$@"
}
set -x
identity identity identity identity identity echo Hello \"World\"
# + identity identity identity identity identity echo Hello '"World"'
# + identity identity identity identity echo Hello '"World"'
# + identity identity identity echo Hello '"World"'
# + identity identity echo Hello '"World"'
# + identity echo Hello '"World"'
# + echo Hello '"World"'
# Hello "World"

1
स्पष्टीकरण के लिए धन्यवाद। बस grep उपनाम के लिए "$ *" का उपयोग किया।
अंधेरा

तुम मेरा दिन बचाओ!
xyz
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.