शबंग (यानी #!) के साथ जाग के लिए कई तर्कों का उपयोग कैसे करें?


118

मैं एक शगुन--re-interval का उपयोग करने के साथ एक gawk स्क्रिप्ट निष्पादित करना चाहते हैं । के "भोले" दृष्टिकोण

#!/usr/bin/gawk --re-interval -f
... awk script goes here

काम नहीं करता है, क्योंकि गौक को पहले तर्क "--re-interval -f"(व्हॉट्सएप के आसपास नहीं) के साथ कहा जाता है , जिसे यह समझ में नहीं आता है। क्या इसके लिए वर्कअराउंड है?

बेशक आप या तो सीधे gawk को कॉल नहीं कर सकते हैं, लेकिन इसे शेल स्क्रिप्ट में लपेटते हैं, जो पहले तर्क को विभाजित करता है, या शेल स्क्रिप्ट बनाता है, जो तब gawk को कॉल करता है और स्क्रिप्ट को किसी अन्य फ़ाइल में डाल देता है, लेकिन मैं सोच रहा था कि क्या कोई तरीका है यह एक फ़ाइल के भीतर है।

शेबबैंग लाइनों का व्यवहार सिस्टम से सिस्टम तक भिन्न होता है - कम से कम साइगविन में यह व्हाट्सएप द्वारा तर्कों को विभाजित नहीं करता है। मैं बस इस बात की परवाह करता हूं कि इसे उस प्रणाली पर कैसे किया जाए जो उस तरह का व्यवहार करता है; स्क्रिप्ट पोर्टेबल होने का मतलब नहीं है।


1
एक मूर्खतापूर्ण प्रयोग जो मैंने अभी किया था, वह एक स्क्रिप्ट के साथ एक और स्क्रिप्ट का उपयोग कर रहा था, जो कि शेबिंग लाइन पर था, जिसने तर्कों को सही ढंग से विभाजित किया।
हस्त्कर्ण

@ हस्त्कुर्कन, जो एक और मुद्दा उठाता है, कि शबंग रेखाओं का व्यवहार भी सिस्टम से सिस्टम wrt में भिन्न होता है, क्या आह्वान किया गया प्रोग्राम स्वयं एक स्क्रिप्ट हो सकता है।
डबियसजिम


Gawk (> = 4.0) के हाल के संस्करणों के साथ, --re-intervalअब और ज़रूरत नहीं है (देखें [ gnu.org/software/gawk/manual/… )।

जवाबों:


25

यह मेरे साथ काम करने के लिए लगता है (छ) awk।

#!/bin/sh
arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"


# The real awk program starts here
{ print $0 }

#!रनों पर ध्यान दें /bin/sh, इसलिए इस स्क्रिप्ट को पहली बार शेल स्क्रिप्ट के रूप में व्याख्या किया गया है।

सबसे पहले, मैंने बस कोशिश की "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@", लेकिन awk ने एक आदेश के रूप में व्यवहार किया और बिना इनपुट के हर पंक्ति को मुद्रित किया। यही कारण है कि मैं अंदर डाल दिया arbitrary_long_name==0- यह हर समय विफल माना जाता है। आप इसे कुछ अस्पष्ट स्ट्रिंग के साथ बदल सकते हैं। मूल रूप से, मैं जाग में एक गलत स्थिति की तलाश में था जो शेल स्क्रिप्ट पर प्रतिकूल प्रभाव नहीं डालेगी।

शेल स्क्रिप्ट में, arbitrary_long_name==0एक चर को परिभाषित करता है arbitrary_long_nameऔर इसे इसके बराबर सेट करता है =0


यह मेरा उत्तर है, लेकिन मुझे आश्चर्य है कि क्या यह पर्याप्त रूप से पोर्टेबल और मजबूत है। क्या यह विशेष रूप से निर्भर करता है bash, या यह किसी भी POSIX के साथ काम करेगा sh? और मैं awkअक्सर उपयोग नहीं करता हूं , इसलिए मुझे यकीन नहीं है कि दूसरी पंक्ति पर मेरी चाल लाइन awkको अनदेखा करने के लिए मजबूर करने का एक अच्छा तरीका है ।
हारून मैकडैड

बस मैं क्या सोच रहा था, +1, लेकिन शायद असावधान (इसलिए रिश्तेदार वोट)।
हारून हॉल

क्या आप बता सकते हैं कि इसमें क्या समस्याएँ हो सकती हैं, @AaronHall? जब तक arbitrary_long_nameवैरिएबल वास्तविक awk प्रोग्राम में उपयोग किए जाने वाले वैरिएबल से टकराता नहीं है, मैं किसी भी मुद्दे को नहीं देख सकता। क्या मुझे कुछ याद आ रहा है?
आरोन मैकडैड

स्क्रिप्ट को संभवतः खतरनाक तरीके से दुर्व्यवहार से बचाने के #!/bin/sh -बजाय उपयोग करें #!/bin/shयदि -पहले वर्ण के रूप में एक शून्य तर्क के साथ लागू किया गया हो। यह सी जैसी प्रोग्रामिंग भाषाओं में आकस्मिक रूप से हो सकता है, जहां तर्क प्रोग्राम को पास execveऔर इसी तरह के फ़ंक्शंस के हिस्से के रूप में भूलकर गलती से गड़बड़ करना आसान है , और अगर लोग आदतन इसकी रक्षा करना भूल जाते हैं, तो यह भी हो सकता है अंत में एक दुर्भावनापूर्ण शोषक भेद्यता में अंतिम चरण है जो एक हमलावर को एक इंटरैक्टिव शेल प्राप्त करने देता है।
mtraceur

161

शेबबैंग लाइन को पोसिक्स, एसयूएस, एलएसबी या किसी अन्य विनिर्देश के हिस्से के रूप में निर्दिष्ट नहीं किया गया है। AFAIK, यह भी ठीक से प्रलेखित नहीं किया गया है।

के बीच सब कुछ ले: वहाँ के बारे में क्या यह है एक किसी न किसी आम सहमति नहीं है !और \nऔर execयह। धारणा यह है कि !और \nदुभाषिया के बीच सब कुछ एक पूर्ण निरपेक्ष पथ है। अगर इसमें व्हाट्सएप हो तो क्या होगा, इस बारे में कोई सहमति नहीं है।

  1. कुछ ऑपरेटिंग सिस्टम केवल पथ के रूप में पूरी चीज़ का इलाज करते हैं। आखिरकार, अधिकांश ऑपरेटिंग सिस्टमों में, व्हाट्सएप या डैश एक मार्ग में कानूनी हैं।
  2. कुछ ऑपरेटिंग सिस्टम व्हॉट्सएप पर विभाजित हो जाते हैं और पहले भाग को दुभाषिया और बाकी हिस्सों को व्यक्तिगत तर्कों के रूप में मानते हैं।
  3. कुछ ऑपरेटिंग सिस्टम पहले व्हाट्सएप पर विभाजित हो जाते हैं और सामने वाले हिस्से को इंटरपीटर और शेष भाग को एक ही तर्क के रूप में मानते हैं (जो कि आप देख रहे हैं)।
  4. कुछ लोग तो कुटिया लाइनों का समर्थन नहीं करते सब पर

शुक्र है, 1. और 4. की मृत्यु हो गई लगती है, लेकिन 3. बहुत व्यापक है, इसलिए आप बस एक से अधिक तर्क पारित करने में सक्षम होने पर भरोसा नहीं कर सकते।

और चूंकि कमांड का स्थान भी POSIX या SUS में निर्दिष्ट नहीं है, आप आमतौर पर निष्पादन के नाम को पारित करके उस तर्क का उपयोग करते हैं envताकि यह निष्पादन योग्य स्थान को निर्धारित कर सके; उदाहरण के लिए:

#!/usr/bin/env gawk

[जाहिर है, यह अभी भी के लिए एक विशेष पथ मानता है env, लेकिन केवल कुछ ही प्रणालियां हैं जहां यह रहता है /bin, इसलिए यह आम तौर पर सुरक्षित है। के स्थान envके स्थान तुलना में बहुत अधिक मानकीकृत है gawkया जैसे भी बदतर कुछ pythonया rubyया spidermonkey।]

जिसका अर्थ है कि आप वास्तव में उपयोग नहीं कर सकते किसी भी तर्क बिल्कुल


1
FreeBSD के env में एक -Sस्विच है जो यहाँ मदद करता है, लेकिन यह मेरे लिनक्स पर मौजूद नहीं है env, और मुझे संदेह है कि यह gygwin पर उपलब्ध नहीं है। @stoerr, विभिन्न परिस्थितियों वाले अन्य उपयोगकर्ता आपके प्रश्नों को बाद में पढ़ सकते हैं, इसलिए सामान्य पोर्टेबल उत्तरों में बेहतर होते हैं, भले ही आपको अब पोर्टेबिलिटी की आवश्यकता न हो।
डबियसजिम

4
इसलिए हम किसी शेबांग में तर्कों का उपयोग नहीं कर सकते हैं। लेकिन क्या होगा अगर हमें किसी भी तरह से तर्कों की आवश्यकता है? मुझे लग रहा है कि समाधान एक आवरण खोल स्क्रिप्ट युक्त #!/bin/shऔर लिखने के लिए है /usr/bin/env gawk --re-interval -f my-script.awk। क्या वो सही है?
रोरी ओ'केन जूल

1
मैं इससे सहमत नहीं हूँ। आप एक तर्क का उपयोग बहुत कम कर सकते हैं। कोई भी प्रणाली जहां आप किसी भी तर्क का उपयोग नहीं कर सकते हैं, इस पारंपरिक यूनिक्सवाद को लागू करने में बुरी तरह विफल रहता है, जो हैश-बैंग है। यदि गैर-कार्यान्वयन उचित खेल है, तो हम सुरक्षित रूप से कह सकते हैं कि #!स्वयं पोर्टेबल नहीं है। उदाहरण के लिए, विंडोज इस सम्मेलन को "मूल रूप से" बिल्कुल नहीं पहचानता है। परंपरागत रूप से करने में सक्षम यूनिक्स पर एक-एक तर्क की धमाकेदार जरूरत है #!/usr/bin/awk -f
कज़

7
@ काज़: हाँ, लेकिन चूंकि कई बायनेरिज़ के रास्ते मानकीकृत नहीं हैं, आप अपने एक तर्क का उपयोग #!/usr/bin/env rubyया पसंद के लिए करते हैं।
जोर्ग डब्ल्यू मित्तग

3
@ स्पेसर: पोसिक्स विनिर्देश को बदलें और 20-30 वर्षों तक प्रतीक्षा करें जब तक कि सभी सिस्टम को युक्ति के साथ अद्यतन नहीं किया गया हो।
जॉर्ग डब्ल्यू मित्तग

18

हालाँकि बिल्कुल पोर्टेबल नहीं है, जो कोरुटिल्स 8.30 से शुरू होता है और इसके प्रलेखन के अनुसार आप इसका उपयोग कर पाएंगे:

#!/usr/bin/env -S command arg1 arg2 ...

इसलिए दिया गया:

$ cat test.sh
#!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too

तुम्हे मिल जाएगा:

% ./test.sh 
$0 is '/usr/local/bin/showargs'
$1 is 'here'
$2 is 'is another'
$3 is 'long'
$4 is 'arg'
$5 is '-e'
$6 is 'this and that '
$7 is 'too'
$8 is './test.sh'

और अगर आप उत्सुक हैं showargsतो:

#!/usr/bin/env sh
echo "\$0 is '$0'"

i=1
for arg in "$@"; do
    echo "\$$i is '$arg'"
    i=$((i+1))
done

मूल उत्तर यहाँ


1
FYI करें, FreeBSD के पास वर्षों से (6.0 के बाद से) है। यह कोरटिल्स के अलावा एक स्वागत योग्य पोर्टेबिलिटी है।
जुआन

12

मैं उसी मुद्दे पर आया था, जिस तरह से व्हाट्सएप को एक शेबंग (कम से कम लिनक्स पर) से निपटाए जाने के कारण कोई स्पष्ट समाधान नहीं है।

हालांकि, अगर आप एक कुटिया में कई विकल्प पारित कर सकते हैं, जब तक कि वे कर रहे हैं कम विकल्प और वे किया जा सकता है concatenated (जीएनयू रास्ता)।

उदाहरण के लिए, आपके पास नहीं हो सकता

#!/usr/bin/foo -i -f

लेकिन आप कर सकते हैं

#!/usr/bin/foo -if

जाहिर है, यह केवल तभी काम करता है जब विकल्पों में कम समतुल्य हों और कोई तर्क न लें।


11

सबग्विन और लिनक्स के तहत शेबंग के रास्ते के बाद सब कुछ एक तर्क के रूप में कार्यक्रम के लिए पार्स हो जाता है।

awkशेबंग के अंदर एक और स्क्रिप्ट का उपयोग करके इसके चारों ओर हैक करना संभव है :

#!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}

यह {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}awk में निष्पादित करेगा ।
और यह /usr/bin/gawk --re-interval -f path/to/your/script.awkआपके सिस्टम शेल में निष्पादित होगा ।


2
इस अभ्यस्त काम अगर आप पटकथा के लिए तर्कों पारित कर दिया
स्टीवन पेनी

4
#!/bin/sh
''':'
exec YourProg -some_options "$0" "$@"
'''

ऊपर शेल शेलबंग चाल की तुलना में अधिक पोर्टेबल है /usr/bin/env


'' ':' एक होल्ड-ओवर है क्योंकि मेरा मूल समाधान एक पायथन स्क्रिप्ट के लिए था इसलिए '' ':' 'अजगर इंटरप्रेटर को निष्पादन भाग को अनदेखा करने के लिए कहता है।
user3123730

4
मुझे लगता है कि आप को नीचा दिखाया जा रहा है क्योंकि आपका समाधान है python, लेकिन यह सवाल है awk
हारून मैकडैड

1
अजगर के लिए महान हैक।
ज़ार है

3

Gawk मैन्युअल (http://www.gnu.org/manual/gawk/gawk.html) में, अनुभाग 1.14 का अंत ध्यान दें कि आपको केवल एक तर्क का उपयोग करना चाहिए जब एक शेबंग लाइन से gkk चला रहे हों। यह कहता है कि OS एकल तर्क के रूप में gawk करने के पथ के बाद सब कुछ व्यवहार करेगा। शायद --re-intervalविकल्प को निर्दिष्ट करने का एक और तरीका है ? शायद आपकी स्क्रिप्ट शेल शेल लाइन में आपके शेल को संदर्भित कर सकती है, gawkकमांड के रूप में चला सकती है , और आपकी स्क्रिप्ट के टेक्स्ट को "यहां दस्तावेज़" के रूप में शामिल कर सकती है।


ऐसा लगता है कि विकल्प को निर्दिष्ट करने का कोई अन्य तरीका नहीं है। आप सही हैं: gawk -f - << EOF, स्क्रिप्ट की कुछ लाइनें, EOF काम करता है, लेकिन यह मुझे gawk के साथ मानक इनपुट पढ़ने से रोकता है।
हंस-पीटर स्टोअर

यहाँ दस्तावेज़ मानक इनपुट स्ट्रीम के लिए खाता है gawk, लेकिन आप अभी भी stderr पर कुछ पाइप करने में सक्षम हो सकते हैं (यानी, इस स्क्रिप्ट में पाइप करने से पहले stderr पर रीडायरेक्ट को रीडायरेक्ट करते हैं)। मैंने वास्तव में कभी कोशिश नहीं की है, लेकिन जब तक पहली प्रक्रिया stderr पर कुछ भी उत्सर्जित नहीं करती है, तब तक यह काम कर सकता है। आप एक नामांकित पाइप ( linuxjournal.com/content/use-onym-pipes-fifos-bash ) भी बना सकते हैं यदि आप यह सुनिश्चित करना चाहते हैं कि और कुछ भी इसका उपयोग नहीं कर रहा है।
bta

3

का उपयोग नहीं क्यों bashऔर gawkही है, अतीत कुटिया छोड़ स्क्रिप्ट पढ़ी, और का एक दूसरा उदाहरण के लिए एक फ़ाइल के रूप में पारित करने के लिए gawk [--with-whatever-number-of-params-you-need]?

#!/bin/bash
gawk --re-interval -f <(gawk 'NR>3' $0 )
exit
{
  print "Program body goes here"
  print $1
}

(-वह स्वाभाविक रूप से भी उदाहरण के लिए sedया के साथ पूरा किया जा सकता है tail, लेकिन मुझे लगता है कि केवल bashऔर केवल पर निर्भर करता है कि किसी प्रकार की सुंदरता gawkहै;)


0

बस मज़े के लिए: निम्नलिखित काफी अजीब समाधान है जो स्टड और प्रोग्राम को फाइल डिस्क्रिप्टर 3 और 4 के माध्यम से पुन: प्रसारित करता है। आप स्क्रिप्ट के लिए एक अस्थायी फ़ाइल भी बना सकते हैं।

#!/bin/bash
exec 3>&0
exec <<-EOF 4>&0
BEGIN {print "HALLO"}
{print \$1}
EOF
gawk --re-interval -f <(cat 0>&4) 0>&3

एक बात इस बारे में कष्टप्रद है: शेल स्क्रिप्ट पर चर विस्तार करता है, इसलिए आपको हर $ (जैसा कि स्क्रिप्ट की दूसरी पंक्ति में किया गया है) उद्धृत करना होगा और शायद उससे अधिक।


-1

पोर्टेबल समाधान के लिए, awkइसके बजाय का उपयोग करें gawk, /bin/shअपने शेबंग के साथ मानक बोर्न शेल ( ) को लागू करें, और awkसीधे आह्वान करें, कमांड लाइन पर कार्यक्रम को स्टड के बजाय यहां दस्तावेज़ के रूप में पारित करें:

#!/bin/sh
gawk --re-interval <<<EOF
PROGRAM HERE
EOF

नोट: कोई -fतर्क नहीं awk। से इनपुट पढ़ने के stdinलिए उपलब्ध पत्तियां awk। यह मानते हुए कि आपने gawkस्थापित किया है और आपके पास PATH, वह सब कुछ प्राप्त करता है जो मुझे लगता है कि आप अपने मूल उदाहरण के साथ करने की कोशिश कर रहे थे (यह मानते हुए कि आप फ़ाइल सामग्री को awk script होना चाहते हैं और इनपुट नहीं है, जो मुझे लगता है कि आपके shebang दृष्टिकोण ने इसका इलाज किया होगा। )।


3
यह मेरे लिए काम नहीं किया। बैश आदमी कहते हैं, <<< ब्लाबला स्टड पर ब्लाबला डालता है। क्या आपका मतलब है << - EOF? किसी भी तरह से, यह भी स्टड पर कार्यक्रम डालता है।
हंस-पीटर स्टॉर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.