Shebang में `/ usr / बिन / env sed -f` का उपयोग करने का तरीका?


25

/usr/bin/env sed -fटर्मिनल कार्यों में टाइपिंग ।

लेकिन अगर इसे एक शेबंग के रूप में उपयोग करें,

#!/usr/bin/env sed -f 
s/a/b/

स्क्रिप्ट निष्पादित करने में विफल रहेगी:

/usr/bin/env: sed -f: No such file or directory

मुझे विश्वास है कि यह -f से संबंधित है। लेकिन इसका समाधान कैसे किया जाए?


जवाबों:


33

आप, एक #!लाइन पर एक से अधिक तर्क नहीं दे सकते हैं । इसका मतलब है कि केवल एक पूर्ण पथ और एक तर्क (जैसे #!/bin/sed -fया #!/usr/bin/sed -f), या #!/usr/bin/envदुभाषिया का कोई तर्क नहीं।

एक पोर्टेबल स्क्रिप्ट प्राप्त करने के लिए एक वर्कअराउंड का उपयोग करना है #!/bin/shऔर एक शेल-रैपर, कमांड-लाइन तर्क के रूप में सेड स्क्रिप्ट को पास करना है। ध्यान दें कि यह POSIX द्वारा अनुमोदित नहीं है ( -eपोर्टेबिलिटी के लिए प्रत्येक निर्देश के लिए एक अलग तर्क के साथ बहु-निर्देश स्क्रिप्ट को लिखा जाना चाहिए ), लेकिन यह कई कार्यान्वयनों के साथ काम करता है।

#!/bin/sh
exec sed '
s/a/b/
' "$@"

एक लंबी स्क्रिप्ट के लिए, एक हेरेडोक का उपयोग करना अधिक सुविधाजनक हो सकता है। एक वंशानुगत का एक फायदा यह है कि आपको किसी भी उद्धरण को अंदर उद्धृत करने की आवश्यकता नहीं है, यदि कोई हो। एक प्रमुख नकारात्मक पक्ष यह है कि स्क्रिप्ट को इसके मानक इनपुट पर दो कष्टप्रद परिणामों के साथ sed करने के लिए खिलाया जाता है। सीड के कुछ संस्करणों की आवश्यकता होती -f /dev/stdinहै -f -, जो पोर्टेबिलिटी के लिए एक समस्या है। इससे भी बदतर, स्क्रिप्ट एक फिल्टर के रूप में कार्य नहीं कर सकती है, क्योंकि मानक इनपुट स्क्रिप्ट है और डेटा नहीं हो सकता है।

#!/bin/sh
exec sed -f - -- "$@" <<'EOF'
s/a/b/
EOF

हेरेडोक के नकारात्मक पक्ष को एक उपयोगी उपयोग द्वारा सुधारा जा सकता है cat। चूंकि यह पूरी स्क्रिप्ट को फिर से कमांड लाइन पर रखता है, इसलिए यह POSIX- अनुरूप नहीं है, लेकिन मोटे तौर पर व्यवहार में पोर्टेबल है।

#!/bin/sh
exec sed "$(cat <<'EOF')" -- "$@"
s/a/b/
EOF

एक और वर्कअराउंड एक स्क्रिप्ट लिखना है जिसे sh और sed दोनों द्वारा पार्स किया जा सकता है। यह पोर्टेबल है, उचित रूप से कुशल है, बस थोड़ा बदसूरत है।

#! /bin/sh
b ()
{
x
}
i\
f true; then exec sed -f "$0" "$@"; fi
: ()
# sed script starts here
s/a/b/

स्पष्टीकरण:

  • श के तहत: एक फ़ंक्शन को परिभाषित करना b; जब तक फ़ंक्शन सिंटैक्टली रूप से अच्छी तरह से गठित नहीं हो जाता है तब तक कोई फर्क नहीं पड़ता (विशेष रूप से, आपके पास खाली फ़ंक्शन नहीं हो सकता)। फिर अगर सच (यानी हमेशा), sedस्क्रिप्ट पर अमल करें।
  • सेड के तहत: ()लेबल की शाखा , फिर कुछ सुव्यवस्थित इनपुट। फिर एक iकमांड, जिसका कोई प्रभाव नहीं है क्योंकि यह हमेशा स्किप हो जाता है। अंत में ()स्क्रिप्ट के उपयोगी भाग के बाद लेबल।
  • जीएनयू सेड, बिजीबॉक्स और ओपनबीएसडी के तहत परीक्षण किया गया। (आप GNU sed पर कुछ सरल के साथ दूर हो सकते हैं, लेकिन OpenBSD sed, उन भागों के बारे में उपयुक्त है जो इसे छोड़ देता है।)

1
"या #!/usr/bin/envकोई तर्क नहीं।" बहुत अच्छी तरह से प्रकाशित नहीं किया गया है। शायद "या #!/usr/bin/env sedकोई तर्क नहीं है।"
cjm

+1 के लिए "बस थोड़ा सा बदसूरत" और दोहरी भाषा की स्क्रिप्ट :)
पूर्वव्यापी

6

ओएस के आधार पर शेबंग (#!) के विभिन्न असंगत कार्यान्वयन हैं। कुछ पूर्ण तर्क सूची का निर्माण कर रहे हैं, कुछ कमांड पथ को संरक्षित कर रहे हैं और शेष सभी तर्कों को एक ही के रूप में डाल रहे हैं, कुछ सभी तर्कों को अनदेखा कर रहे हैं और केवल कमांड पथ को पारित कर रहे हैं, और अंत में, कुछ पूरे स्ट्रिंग को एकल के रूप में पास कर रहे हैं आदेश। आप बाद के मामले में प्रतीत होते हैं।


2

env "sed -f" नाम से एक फ़ाइल खोजने की कोशिश कर रहा है। आप "#! / Usr / bin / sed -f" को अपनी शबंग रेखा के रूप में आज़मा सकते हैं।


2

GNU coreutils v8.30 के अनुसार , आप यह कर सकते हैं:

#!/usr/bin/env -S sed -f

यह सुविधा एक हाल ही में (2018/04/20) में जोड़ा गया है प्रतिबद्ध करने के लिए env.cGNU coreutils पैकेज है, जो जोड़ा में -Sया --split-stringविकल्प।

से envआदमी पेज:

OPTIONS
-S/--split-string usage in scripts
    The  -S  option allows specifing multiple parameters in a script.
    Running a script named 1.pl containing the following first line:

            #!/usr/bin/env -S perl -w -T

    Will execute perl -w -T 1.pl .

    Without the '-S' parameter the script will likely fail with:

            /usr/bin/env: 'perl -w -T': No such file or directory

    See the full documentation for more details.

अधिक उदाहरण GNU कोरुटिल्स मैनुअल में उपलब्ध हैं ।

यदि आप -vवर्बोज़ आउटपुट के लिए विकल्प का उपयोग करते हैं , तो आप देख सकते हैं कि कैसे envतर्कों के स्ट्रिंग को विभाजित किया जाता है:

इन my_sed_script.sed:

#!/usr/bin/env -vS sed -f
s/a/b/

निष्पादन:

$ ./my_sed_script.sed
split -S:  ‘sed -f’
 into:    ‘sed’
     &    ‘-f’
executing: sed
   arg[0]= ‘sed’
   arg[1]= ‘-f’
   arg[2]= ‘./my_sed_script.sed’

नोट: यह केवल उन छतों पर लागू होता है जो विशेष रूप से GNU की एक विशेषता के /usr/bin/envरूप --split-stringमें उपयोग करते हैं env


1

यह उत्तर एक सुरुचिपूर्ण समाधान का मार्ग प्रदान करता है: /programming//a/1655389/642372

  1. read एक शेल चर में एक वंशानुगत।
  2. उस चर को स्थितीय तर्क के रूप में पास करें sed

नमूना:

#!/usr/bin/env bash

read -rd '' SED_SCRIPT <<EOD      
# Your sed script goes here.
s/a/b/
EOD

exec sed "$SED_SCRIPT" "$@"

1

मुझे वाकर का समाधान पसंद है, लेकिन इसमें सुधार किया जा सकता है (इसे अलग उत्तर में रखा जा सकता है क्योंकि टिप्पणियाँ पूर्व-लिखित पाठ को स्वीकार नहीं करती हैं)। यह लिनक्स या बैश के सभी संस्करणों पर काम नहीं कर सकता है, लेकिन उबंटू 17.10 पर आप इसे नीचे कर सकते हैं:

#!/usr/bin/env bash
read SED_SCRIPT <<EOD
s/a/b/
EOD
sed "$SED_SCRIPT" "$@"

आप इसे हटा सकते हैं evalऔर readकमांड को सरल कर सकते हैं , लेकिन आपको हेरेडोक के अंदर टिप्पणी से छुटकारा पाना होगा।

इसके अलावा, सब कुछ के लिए आप कभी भी sed के बारे में जानना चाहते थे लेकिन पूछने से डरते थे, http://www.grymoire.com/unix/sed.html पर एक बहुत ही उपयोगी ट्यूटोरियल है । यह एक बेहतर उपाय बताता है, हारने /usr/bin/envकी राह पर और हार्ड-कोडिंग करने की कीमत पर :

#!/bin/sed -f
s/a/b/
s/c/d/

यह एक से अधिक s///प्रतिस्थापन का समर्थन करने का अतिरिक्त लाभ है ।

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