शेबंग `// 'से शुरू होता है?


60

मैं निम्नलिखित स्क्रिप्ट ( hello.go) के बारे में उलझन में हूं ।

//usr/bin/env go run $0 $@ ; exit

package main
import "fmt"
func main() {
    fmt.Printf("hello, world\n")
}

यह निष्पादित कर सकता है। (MacOS X 10.9.5 पर)

$ chmod +x hello.go
$ ./hello.go
hello, world

मैंने शेबंग के साथ शुरू होने के बारे में नहीं सुना है //। और यह तब भी काम कर रहा है जब मैं स्क्रिप्ट के शीर्ष पर एक रिक्त रेखा सम्मिलित करता हूं। यह स्क्रिप्ट क्यों काम करती है?


//&>/dev/null;x="${0%.*}";[ ! "$x" -ot "$0" ]||(rm -f "$x";cc -o "$x" "$0")&&exec "$x" "$@" ...
पुनर्निर्देशित मोनासा -जेर्मा बैंक्स

2
नीचे @ g-man और Jörg कमेंट्स के बाद, और gilles उत्तर ( unix.stackexchange.com/a/1919/27616 ) के अनुसार , इस ट्रिक का उपयोग सबसे अधिक संगत करने के ///....बजाय करना चाहिए //...!
ओलिवियर दुलैक

1
यह अधिक उद्धरण के बिना रिक्त स्थान के साथ तर्कों (या किसी निर्देशिका में स्थान) को सही ढंग से नहीं लेगा:go run "$0" "$@"
चार्ल्स डफी

जवाबों:


71

यह एक शेबांग नहीं है, यह सिर्फ एक स्क्रिप्ट है जो डिफ़ॉल्ट शेल द्वारा चलाई जाती है। शेल पहली पंक्ति को निष्पादित करता है

//usr/bin/env go run $0 $@ ; exit 

जो goइस फ़ाइल के नाम से जुड़ा हुआ है, इसलिए इसका परिणाम यह है कि इस फाइल को गो स्क्रिप्ट के रूप में चलाया जाता है और फिर शेल शेष फ़ाइल को देखे बिना निकल जाता है।

लेकिन //सिर्फ /एक या उचित शेबंग के बजाय क्यों शुरू करें #!?

ऐसा इसलिए है क्योंकि फ़ाइल को एक मान्य गो स्क्रिप्ट होना चाहिए, या गो शिकायत करेगा। जाने में, वर्ण //एक टिप्पणी को निरूपित करते हैं, इसलिए गो पहली पंक्ति को एक टिप्पणी के रूप में देखते हैं और इसकी व्याख्या करने का प्रयास नहीं करते हैं। #हालांकि, चरित्र एक टिप्पणी को निरूपित नहीं करता है, इसलिए एक सामान्य गड़बड़ी का परिणाम तब होगा जब फ़ाइल की व्याख्या करने में त्रुटि होगी।

सिंटैक्स का यह कारण सिर्फ एक फ़ाइल का निर्माण करना है जो शेल स्क्रिप्ट और गो स्क्रिप्ट दोनों के बिना एक-दूसरे पर कदम रखने के लिए है।


10
यह कर्नेल द्वारा संभाला जाता है, शेल नहीं; देखें कि कैसे लिनक्स कई पथ विभाजकों (/ home //// उपयोगकर्ता नाम /// फ़ाइल) को हैंडल करता है
जी-मैन

3
@HermanTorjussen फ़ीचर - रास्तों का पर्यायवाची शब्द बहुत अच्छी तरह से परिभाषित किया गया है, जिससे बहुत सारे उपयोगी वेरिएंट की अनुमति मिलती है - और शक्ति के साथ जटिलता आती है: /जैसा कि पथ प्रत्यय के रूप में परिभाषित किया गया है /.; जब aकोई सिमलिंक नहीं है, aतो वही है a/जो कि a/.थेर के समान है ऐसे मामले हैं जहां एक मार्ग /अर्थ में कोई बदलाव नहीं के साथ एक अतिरिक्त प्राप्त कर सकता है। जब एक विहित मार्ग प्राप्त होता है, तो एक स्लैश को लगातार एक करने के लिए एक सामान्यीकरण चरण होता है। दी, यह औपचारिक वाक्यविन्यास का एक साफ हिस्सा नहीं है, हालांकि।
वोल्कर सेगेल

13
दरअसल, POSIX का कहना है कि मल्टीपल स्लैश एक ही स्लैश के समान हैं, सिवाय इसके जब पथ के बिल्कुल शुरुआत में दो स्लैश होते हैं। जैसा कि यहां है। उस मामले में, पथ की व्याख्या कार्यान्वयन-निर्भर है: "यदि एक पथनाम दो क्रमिक <स्लेश> वर्णों से शुरू होता है, तो पहला घटक प्रमुख स्लैश> वर्णों का अनुसरण कार्यान्वयन-परिभाषित तरीके से किया जा सकता है, हालाँकि इससे अधिक दो प्रमुख <स्लेश> वर्णों को एकल <स्लैश> वर्ण माना जाएगा।
जोर्ग डब्ल्यू मित्तग

11
इसलिए, इसे पोर्टेबल बनाने के लिए इसके बजाय लिखना चाहिए ///usr/bin/env go run $0 $@ ; exit...
रुस्लान

1
@ लेग शेल बाहर निकलता है लेकिन गो दुभाषिए को लॉन्च करने से पहले नहीं। गो मुद्रण जगत को नमस्कार है, शैल नहीं।
केसी

8

यह चलता है क्योंकि डिफ़ॉल्ट रूप से निष्पादन योग्य फ़ाइल को / बिन / श स्क्रिप्ट माना जाता है। यानी यदि आपने कोई विशेष शेल निर्दिष्ट नहीं किया है - यह #! / Bin / sh है।

// को केवल पथों में अनदेखा किया जाता है - आप विचार कर सकते हैं कि यह एकल '/' है।

तो आप विचार कर सकते हैं कि आपके पास पहली पंक्ति के साथ शेल स्क्रिप्ट है:

/usr/bin/env go run $0 $@ ; exit

यह लाइन क्या करती है? यह पैरेंट्स के 'रन रन $ 0 $ @' के साथ 'एनवी' चलाता है। वहाँ 'go' कमांड है और 'रन $ 0 $ @' args हैं और इसके बाद स्क्रिप्ट से बाहर निकलते हैं। $ 0 इस लिपि का नाम है। $ @ मूल स्क्रिप्ट तर्क हैं। तो यह लाइन चलती है जो इस स्क्रिप्ट को तर्क के साथ चलाता है

काफी दिलचस्प विवरण हैं, जैसा कि टिप्पणियों में कहा गया है, कि दो स्लैश कार्यान्वयन-परिभाषित हैं, और यह स्क्रिप्ट तीन या अधिक स्लैशों को निर्दिष्ट करने पर पॉसिक्स-सही हो जाएगी। रास्तों में स्लैश को कैसे संभाला जाना चाहिए, इसके विवरण के लिए http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html देखें ।

यह भी ध्यान दें कि स्क्रिप्ट में $ @ की एक और गलती है, इसके बजाय "$ @" का उपयोग करना सही है, क्योंकि अन्यथा यदि किसी भी पैरामीटर में रिक्त स्थान है तो इसे कई मापदंडों में विभाजित किया जाएगा। उदाहरण के लिए यदि आप "$ @" का उपयोग नहीं कर रहे हैं तो आप रिक्त स्थान के साथ फ़ाइल का नाम नहीं दे सकते

यह विशेष स्क्रिप्ट स्पष्ट रूप से इस विचार पर निर्भर करती है कि '//' '/' के बराबर है


9
"// // केवल पथों में नजरअंदाज किया जाता है" - यह गारंटी नहीं है: "यदि एक पथनाम दो क्रमिक <स्लेश> वर्णों से शुरू होता है, तो प्रमुख <स्लेश> वर्णों का अनुसरण करने वाला पहला घटक कार्यान्वयन-परिभाषित तरीके से व्याख्या किया जा सकता है" ( पब) .opengroup.org / onlinepubs / 9699919799 / आधारित / ... )
जॉर्ग डब्ल्यू

बहुत ही रोचक, अपडेटेड जवाब।
gena2x

1
... AFS विशेष रूप से लागू / अलग तरीके से, लेकिन यह अब आम नहीं है।
चार्ल्स डफी

0

यह C ++ (और C के लिए काम करेगा, अगर C टिप्पणियों के लिए // अनुमति देता है)

//usr/bin/env sh -c 'p=$(expr '"_$0"' : "_\(.*\)\.[^.]*"); make $p > /dev/null && $p'; exit

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