एक्सेस बैश कमांड लाइन $ @ बनाम $ * आ जाती है


327

कई SO प्रश्नों और बैश ट्यूटोरियल्स में, मैं देखता हूं कि मैं bash स्क्रिप्ट में कमांड लाइन आर्ग्स को दो तरीकों से एक्सेस कर सकता हूं:

$ ~ >cat testargs.sh 
#!/bin/bash

echo "you passed me" $*
echo "you passed me" $@

जिसके परिणामस्वरूप:

$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2

बीच क्या अंतर है $*और $@?
किसी को पूर्व का उपयोग कब करना चाहिए और बाद वाले को कब उपयोग करना चाहिए?


इस उत्तर पर एक नज़र डालें: stackoverflow.com/a/842325/671366
कोडिंग

इंटेलीज में स्थैतिक विश्लेषण echo "something $@"एक त्रुटि के रूप में व्यवहार करता है
एलेक्स कोहेन

जवाबों:


436

अंतर तब प्रकट होता है जब विशेष मापदंडों को उद्धृत किया जाता है। मुझे मतभेदों को स्पष्ट करें:

$ set -- "arg  1" "arg  2" "arg  3"

$ for word in $*; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in $@; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in "$*"; do echo "$word"; done
arg  1 arg  2 arg  3

$ for word in "$@"; do echo "$word"; done
arg  1
arg  2
arg  3

उद्धरण के महत्व पर एक और उदाहरण: ध्यान दें कि "arg" और संख्या के बीच 2 स्थान हैं, लेकिन अगर मैं $ $ उद्धृत करने में विफल रहता हूं:

$ for word in "$@"; do echo $word; done
arg 1
arg 2
arg 3

और बैश में, "$@""डिफ़ॉल्ट" सूची को पुन: व्यवस्थित करने के लिए है:

$ for word; do echo "$word"; done
arg  1
arg  2
arg  3

65
+1 मैंने हमेशा सोचा है कि इस अवधारणा को एक सरल उदाहरण द्वारा प्रदर्शित किया गया था, जिसमें बैश मैनुअल का पूरी तरह से अभाव है।
शेपनर

5
क्या कोई संभावित उपयोग मामला है, जब $*या "$*"आवश्यकता हो सकती है, और उद्देश्य द्वारा सेवा नहीं की जा सकती है $@या नहीं "$@"?
ऐशसेन

5
कौन सा संस्करण "रैपर" स्क्रिप्ट के लिए अधिक उपयुक्त है, जहां स्क्रिप्ट पैरामीटर को एक नए कमांड के लिए पैरामीटर बनने की आवश्यकता है?
सेगफॉल्ट

7
@Segfault, इस मामले में, हमेशा "$@"उद्धरण के साथ चुनें ।
ग्लेन जैकमैन

2
इस उत्तर में उपयोगी उदाहरण हैं, लेकिन बेहतर होगा यदि यह उनके पीछे के तंत्र को भी समझाए। यह इस तरह से काम क्यों करता है?
Lii

255

बैश हैकर्स विकी से एक अच्छा काम अवलोकन तालिका :

$ * बनाम $ @ तालिका

जहां cतीसरी पंक्ति में $IFS, आंतरिक क्षेत्र विभाजक, एक शैल चर का पहला वर्ण है ।

तर्क एक स्क्रिप्ट चर में संग्रहीत करने के लिए कर रहे हैं और तर्क रिक्तियाँ होने की संभावना है, मैं तहे दिल से एक को रोजगार की सिफारिश "$*"आंतरिक क्षेत्र विभाजक के साथ चाल $IFSटैब पर सेट


42
... जहां "सी" $ IFS का पहला चरित्र है
ग्लेन जैकमैन

39
... और $IFS"आंतरिक क्षेत्र विभाजक।"
सर्ज स्ट्रोबैंडैंट

यहां एक उदाहरण है , जिसमें उद्धृत इनपुट शामिल है। इनपुट भी मायने रखता है!
सर्ज स्ट्रोबंड्ट

मान लीजिए कि मैं एक रैपर स्क्रिप्ट बनाना चाहता हूं जो लिपटे हुए कमांड की कार्यक्षमता की नकल करने के अलावा कुछ नहीं करती है। रैपर स्क्रिप्ट से इनर कमांड को पास करने के लिए मुझे किस सिंटैक्स का उपयोग करना चाहिए?
Marinos An

44

$ *

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

$ @

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

स्रोत: बैश आदमी


15

$ @ $ * के समान है, लेकिन प्रत्येक पैरामीटर एक उद्धृत स्ट्रिंग है, अर्थात, पैरामीटर व्याख्या या विस्तार के बिना, बरकरार हैं। इसका मतलब है, अन्य बातों के अलावा, कि तर्क सूची में प्रत्येक पैरामीटर को एक अलग शब्द के रूप में देखा जाता है।

बेशक, "$ @" उद्धृत किया जाना चाहिए।

http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST


1

इस उदाहरण को हम "at" और "asterix" के बीच के अंतर को उजागर कर सकते हैं जबकि हम उनका उपयोग कर रहे हैं। मैंने दो एरे "फल" और "सब्जियां" घोषित किए

fruits=(apple pear plumm peach melon)            
vegetables=(carrot tomato cucumber potatoe onion)

printf "Fruits:\t%s\n" "${fruits[*]}"            
printf "Fruits:\t%s\n" "${fruits[@]}"            
echo + --------------------------------------------- +      
printf "Vegetables:\t%s\n" "${vegetables[*]}"    
printf "Vegetables:\t%s\n" "${vegetables[@]}"    

निम्नलिखित परिणाम देखें कोड ऊपर:

Fruits: apple pear plumm peach melon
Fruits: apple
Fruits: pear
Fruits: plumm
Fruits: peach
Fruits: melon
+ --------------------------------------------- +
Vegetables: carrot tomato cucumber potatoe onion
Vegetables: carrot
Vegetables: tomato
Vegetables: cucumber
Vegetables: potatoe
Vegetables: onion

6
वैज्ञानिक रूप से कहा जाए तो टमाटर फल हैं।
रैंडी

1
आपको अधिकार है! "वनस्पति विज्ञान में, एक फल फूल वाले पौधों में बीज-असर संरचना है (जिसे एंजियोस्पर्म भी कहा जाता है) फूल के बाद अंडाशय से बनता है।" en.wikipedia.org/wiki/Fruit
स्टीफनसन

@ कैंडी: वैज्ञानिक रूप से, सभी फल सब्जियां हैं (यह "पौधे" का पर्याय है)।
क्रिस लुएंगो

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