Bash -c के साथ स्थितीय मापदंडों


15

आमतौर पर, $0एक स्क्रिप्ट में स्क्रिप्ट के नाम पर सेट किया जाता है, या इसे (पथ सहित) के रूप में जो भी लागू किया गया था। हालाँकि, यदि मैं विकल्प के bashसाथ प्रयोग करता हूं, तो कमांड स्ट्रिंग के बाद दिए गए तर्कों में से पहले पर सेट है:-c$0

bash -c 'echo $0 ' foo bar 
# foo 

वास्तव में, ऐसा लगता है कि स्थितिगत मापदंडों को स्थानांतरित कर दिया गया है, लेकिन सहित $0। हालांकि shiftकमांड स्ट्रिंग प्रभावित नहीं करता है $0(सामान्य रूप में):

bash -c 'echo $0; shift; echo $0 ' foo bar
# foo
# foo

कमांड स्ट्रिंग्स के लिए यह स्पष्ट रूप से अजीब व्यवहार क्यों है? ध्यान दें कि मैं इस अजीब व्यवहार को लागू करने के पीछे कारण, औचित्य की तलाश कर रहा हूं।


कोई अनुमान लगा सकता है कि इस तरह के कमांड स्ट्रिंग $0को आमतौर पर परिभाषित पैरामीटर की आवश्यकता नहीं होगी , इसलिए अर्थव्यवस्था के लिए इसका उपयोग सामान्य तर्कों के लिए भी किया जाता है। हालाँकि, उस स्थिति में व्यवहार shiftविषम है। एक अन्य संभावना यह है कि $0कार्यक्रमों के व्यवहार को परिभाषित करने के लिए उपयोग किया जाता है ( जैसा कि एक ला bashकहा जाता है shया जैसा vimकहा जाता है vi), लेकिन ऐसा नहीं हो सकता है, क्योंकि $0यहां केवल कमांड स्ट्रिंग में देखा जाता है और इसके भीतर बुलाए गए कार्यक्रमों द्वारा नहीं। मैं इसके लिए किसी अन्य उपयोग के बारे में नहीं सोच सकता $0, इसलिए मुझे यह समझाने के लिए नुकसान हो रहा है।


एक साइड नोट के रूप में, मैंने एक मुहावरे के रूप में, जैसे के -लिए $0तर्क का उपयोग देखा है sh -c 'foo $1 $2' - a b। इस तरह यह बहुत सामान्य लगता है (एक बार जब आपको पता चला कि -इसका मतलब क्या है, तो वह है)
वोल्कर सिएगेल

तुम भी echo 'echo the other side of this pipe globs "$@"' | sh -s -- *, हालांकि, दुर्भाग्य से, $0आम तौर पर -sधुन विकल्प के साथ एक बसने योग्य पैरामीटर नहीं हो सकता है ... यह xargsआमतौर पर समान तरीकों में से कई में इस्तेमाल किया जा सकता है, हालांकि। और इसके अलावा अन्य।
माइकर्स

@VolkerSiegel अधिक सामान्य होता --, तो कुछ अन्य कार्यक्रमों में देखा गया 'यहाँ से तर्क शुरू होता है' की सामान्य व्याख्या हो सकती थी। तो फिर, कि उन अपरिचितों को भ्रमित करने के -cलिए सोचने के साथ --वास्तव में उस व्याख्या हो सकती है।
मुरु

जवाबों:


10

यह आपको $0इनलाइन स्क्रिप्ट का उपयोग करते समय सेट / चुनने का अवसर देता है । नहीं तो, $0बस हो जाएगा bash

तो आप उदाहरण के लिए कर सकते हैं:

$ bash -c 'wc -c < "${1?}"' getlength foo
4
$ bash -c 'wc -c < "${1?}"' getlength bar
getlength: bar: No such file or directory
$ bash -c 'wc -c < "${1?}"' getlength
getlength: 1: parameter null or not set

सभी गोले ऐसा नहीं करते थे। बॉर्न शेल ने किया। Korn (और Almquist) शेल ने पहले पैरामीटर को $1इसके बजाय जाना चुना । POSIX अंततः बॉर्न के रास्ते के लिए चला गया, इसलिए बाद में kshऔर ashडेरिवेटिव उस पर वापस लौट गए (उस पर अधिक http://www.in-ulm.de/~mascheck/various/find/#shell )। इसका मतलब था कि लंबे समय तक sh(जो कि सिस्टम बॉर्न, अल्मक्विस्ट या कोर्न शेल पर आधारित था) के लिए, आपको नहीं पता था कि पहले तर्क में गया $0या नहीं $1, इसलिए पोर्टेबिलिटी के लिए, आपको ऐसा करना होगा:

sh -c 'echo foo in "$1"' foo foo

या:

sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txt

शुक्र है, POSIX ने नए व्यवहार को निर्दिष्ट किया है जहां पहला तर्क अंदर जाता है $0, इसलिए हम अब इसे आंशिक रूप से कर सकते हैं:

sh -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txt

मैं बस भाग गया: bash -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txtUbuntu 14.04 पर, बैश version 4.3.11(1)-release, और मुझे मिल गया txt files are *.txt:। ऊ
मुरु

2
@ एमुरु, जो सही है (और शायद आपके पास txtवर्तमान निर्देशिका में फाइलें नहीं हैं )। इसे भी देखेंbash -c 'echo "${1?}"' foo
स्टीफन चेजेलस

आह येस। यह एक व्यावहारिक रूप से उपयोगी उदाहरण है।
मुरु

1
sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txtकाल्पनिक रूप से आविष्कारशील है!
इरुवर

या आप एक पूरी तरह से मजबूत वर्कअराउंड का उपयोग करते हैं (comp.unix.shell में Stéphane Chazelas द्वारा सुझाया गया) SHELL -c 'shift $1; command' 2 1 arg1 arg2 ... haha ...
mikeserv

3

यह व्यवहार POSIX द्वारा परिभाषित किया गया है :

sh -c कमांड_नाम [तर्क ...]

कमांड_स्ट्रिंग ऑपरेंड से कमांड पढ़ें। शेष तर्क ऑपरेंड से क्रम में विशेष पैरामीटर 0 ( विशेष पैरामीटर्स देखें ) के मान को कमांड_नाम ऑपरेटर और स्थितीय मापदंडों ($ 1, $ 2, और इसी तरह) के मूल्य से सेट करें।

जैसे आप उस व्यवहार को क्यों चाहते हैं: यह एक स्क्रिप्ट और एक -cस्ट्रिंग के बीच के अंतर को सुचारू करता है। आप किसी भी व्यवहार में बदलाव के बिना सीधे दोनों के बीच रूपांतरण कर सकते हैं। अन्य क्षेत्र इन पर समान होने का भरोसा देते हैं।

यह इस बात के भी अनुरूप है कि प्रोग्राम तर्क सामान्य रूप से कैसे काम करते हैं: यह अंततः एक execफ़ंक्शन को कॉल करने के लिए नीचे आता है , जिसमें पहला प्रदान किया गया तर्क भी है $0, और समान रूप से आमतौर पर यह तर्क उसी तरह होता है जैसे कि आप निष्पादित कर रहे हैं। कभी-कभी, हालांकि, आप वहां एक विशेष मूल्य चाहते हैं, और इसे प्राप्त करने का कोई अन्य तरीका नहीं होगा। यह देखते हुए कि तर्क मौजूद है, इसे किसी चीज़ के लिए मैप करना होगा, और उपयोगकर्ता को यह निर्धारित करने में सक्षम होना चाहिए कि वह क्या है।

यह स्थिरता (और संभावित ऐतिहासिक दुर्घटना) उस स्थिति की ओर ले जाती है जो आप पाते हैं।


क्या आप दूसरे पैरा के लिए (उम्मीद है कि वास्तविक दुनिया) उदाहरण दे सकते हैं?
मुरु

के साथ सादृश्य के साथ सावधान argv[0]$0केवल जब इसे पसंद किया जाता है या इसे argv[0]पारित किया execve()जाता है । स्क्रिप्ट के लिए, तर्क 1, 2 ... के रूप में दिए गए मार्ग पर सेट किया जाता है। shbash$0
स्टीफन चेजलस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.