शेल स्क्रिप्ट में $ {1 + "$ @"} का क्या अर्थ है, और यह "$ @" से कैसे भिन्न होता है?


43

पर्ल दस्तावेज़ीकरण में, perlrun (1) एक द्विभाषी शेल / पर्ल हेडर का उपयोग करके पर्ल स्क्रिप्ट लॉन्च करने का सुझाव देता है:

#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
    if 0;

क्या ${1+"$@"}मतलब है? मैंने "$@"इसके बजाय (बश के रूप में / बिन / श का उपयोग करके) का उपयोग करने की कोशिश की , और यह भी काम करता है।


संपादित करें

नीचे दिए गए दो उत्तर कहते हैं कि यह माना जाता है ${1:+"$@"}। मैं ${parameter:+word}बैश (1) में प्रलेखित ("यूज़ अल्टरनेटिव वैल्यू") सिंटेक्स से अवगत हूँ । हालांकि, मैं असंबद्ध हूं, क्योंकि

  1. दोनों ${1+"$@"}और "$@"ठीक काम करते हैं, भले ही कोई पैरामीटर न हो। अगर मैं simple.sh बनाऊं

    #!/bin/sh
    eval 'exec /usr/bin/perl -x -S -- $0 "$@"'
        if 0;
    #!perl
    use Data::Dumper;
    print Dumper(\@ARGV);
    

    और सवाल

    #!/bin/sh
    eval 'exec /usr/bin/perl -x -S -- $0 ${1+"$@"}'
        if 0;
    #!perl
    use Data::Dumper;
    print Dumper(\@ARGV);
    

    मैं दोनों को पहचान के साथ काम कर सकता हूं:

    $ ./question.sh 
    $VAR1 = [];
    $ ./question.sh a
    $VAR1 = [
              'a'
            ];
    $ ./question.sh a 'b c'
    $VAR1 = [
              'a',
              'b c'
            ];
    $ ./question.sh ""
    $VAR1 = [
              ''
            ];
    $ ./simple.sh 
    $VAR1 = [];
    $ ./simple.sh a
    $VAR1 = [
              'a'
            ];
    $ ./simple.sh a 'b c'
    $VAR1 = [
              'a',
              'b c'
            ];
    $ ./simple.sh ""
    $VAR1 = [
              ''
            ];
    
  2. इंटरनेट पर अन्य स्रोत भी उपयोग करते हैं ${1+"$@"}, जिसमें एक हैकर भी शामिल है जो यह जानता है कि वह क्या कर रहा है।

शायद ${parameter+word}एक अनिर्दिष्ट वैकल्पिक (या पदावनत) वाक्यविन्यास है ${parameter:+word}? क्या कोई उस परिकल्पना की पुष्टि कर सकता है?


जवाबों:


53

यह बॉर्न शेल के साथ संगतता के लिए है। बॉर्न शेल एक पुराना शेल था जिसे पहली बार 1979 में यूनिक्स संस्करण 7 के साथ जारी किया गया था और अभी भी 90 के दशक के मध्य तक /bin/shअधिकांश वाणिज्यिक यूनियनों के रूप में आम था ।

यह सबसे का पूर्वज है बॉर्न की तरह के गोले की तरह ksh, bashया zsh

इसकी कुछ अजीब विशेषताएं थीं, जिनमें से कई में तय किया गया है kshऔर अन्य गोले और नए मानक विनिर्देश हैं sh, जिनमें से एक यह है:

बॉर्न शेल के साथ (कम से कम उन वेरिएंट जहां इसे ठीक नहीं किया गया है): "$@"यदि $# == 0कोई तर्क नहीं है, तो स्थिति के मापदंडों की सूची खाली है ( ) के बजाय एक खाली तर्क का विस्तार होता है ।

${var+something}"कुछ" तक फैलता है जब तक कि $varकोई परेशान न हो। यह स्पष्ट रूप से सभी गोले में प्रलेखित है, लेकिन दस्तावेज में खोजना मुश्किल है bashक्योंकि आपको इस वाक्य पर ध्यान देने की आवश्यकता है:

जब विकल्प के विस्तार का प्रदर्शन नहीं किया जाता है, तो नीचे दिए गए प्रपत्रों का उपयोग करते हुए, एक पैरामीटर के लिए परीक्षण को मारना चाहिए जो परेशान या अशक्त है। केवल एक पैरामीटर के लिए एक परीक्षण में बृहदान्त्र परिणामों को स्वीकार करते हुए जो परेशान है

तो ${1+"$@"}करने के लिए फैलता है "$@"केवल तभी $1सेट किया गया है ( $# > 0) जो चारों ओर से काम करता है कि बॉर्न शैल की सीमा।

ध्यान दें कि उस समस्या के साथ बॉर्न शेल एकमात्र शेल है। आधुनिक shएस (जो कि shपोसिक्स विनिर्देशन के अनुरूप है sh(जो बोर्न शेल नहीं है)) में यह समस्या नहीं है। इसलिए आपको केवल यह चाहिए कि यदि आपको अपने कोड की आवश्यकता है तो बहुत पुरानी प्रणालियों पर जहां /bin/shमानक शेल के बजाय बॉर्न शेल हो सकता है (ध्यान दें कि POSIX मानक के स्थान को निर्दिष्ट नहीं करता है sh, इसलिए Solaris 11 से पहले सोलारिस पर उदाहरण के लिए, /bin/shअभी भी एक बॉर्न शेल था (हालांकि इसमें वह विशेष मुद्दा नहीं था) जबकि सामान्य / मानक shकिसी अन्य स्थान ( /usr/xpg4/bin/sh) में था ।

उस पुराने perlrunपृष्ठ में एक समस्या है, $0हालांकि इसे उद्धृत नहीं किया गया है।

अधिक जानकारी के लिए http://www.in-ulm.de/~mascheck/various/bourne_args/ देखें ।


हिरलूम में प्रजनन नहीं कर सकते। शायद सोलारिस पर लागू नहीं है।
ormaaj

2
@ormaaj। हां, वह पृष्ठ देखें जिससे मैंने लिंक किया था। यह SVR3 में तय किया गया था, और Solaris / SunOS 5 से ऊपर SVR4 पर छूट दी गई थी। और उस पेज में उल्लेख है कि 4.1.x में समस्या नहीं थी।
स्टीफन चेज़लस

ओह समझा। <3 मस्कट पृष्ठ।
ormaaj

3

इस बीच एक अंतर है:

command ""

तथा

command

एक में, आप एक तर्क पारित कर रहे हैं जो एक खाली स्ट्रिंग है। दूसरे में, शून्य तर्क पारित किए गए हैं।

दोनों के लिए, "$ @" समान चीज़ के बराबर होगा "":। लेकिन उपयोग ${1:+"$@"}करना ""पहले के लिए होगा और दूसरे के लिए कोई तर्क पारित नहीं होगा, जो कि इरादा था।

यह महत्वपूर्ण हो जाता है यदि आप नीचे दी गई स्क्रिप्ट को कुछ कर रहे हैं, जिसे sshwrapper कहा जाता है, जिसे आप एक वैकल्पिक कमांड के साथ कहते हैं या एक इंटरैक्टिव शेल प्राप्त करने के लिए कोई तर्क नहीं देते हैं।

: sshwrapper [command]
exec /usr/bin/ssh "${HOSTNAME:-localhost}" "$@"

यह रिमोट होस्ट पर "" चलाने का प्रयास करेगा (जो सिर्फ रिटर्न देता है), यह एक इंटरैक्टिव शेल नहीं होगा।

: sshwrapper [command]
exec /usr/bin/ssh "${HOSTNAME:-localhost}" ${1:+"$@"}

दूरस्थ होस्ट पर एक इंटरेक्टिव शेल शुरू करेगा क्योंकि निष्पादन चर को सही रूप से व्याख्या करेगा, खाली स्ट्रिंग नहीं।

बैश मैनुअल पेजों में "$ {पैरामीटर: + शब्द}" ("वैकल्पिक मूल्य का उपयोग करें") और इसी तरह के चर विस्तार स्ट्रिंग के उपयोग पर पढ़ें।


यह केवल बॉर्न शैल के लिए और लागू करने के लिए लगता है नहीं किसी भी POSIX-conformant के लिए shकार्यान्वयन (अन्य जवाब देखें)।
törzsmókus

4
नहीं, खाली ${1:+"$@"}होने पर कोई तर्क विस्तार नहीं करेगा $1। आप चाहते हैं ${1+"$@"}। मूल रूप से आपने इसे उलट दिया है।
स्टीफन चेजलस

0

मैंने स्टीफन चेज़लस के जवाब का सारांश दिया:

  • $ {1: + "$ @"} परीक्षण यदि $ 1 अशक्त या परेशान है
  • $ 1 + "" $ @ "} परीक्षण अगर $ 1 परेशान

इसलिए यदि पैरामीटर "" के साथ दूसरा उपयोग किया जाता है, तो इसका मतलब है कि $ 1 शून्य है, लेकिन यह परीक्षण नहीं करता है कि यह शून्य है या नहीं, बस यह देखें कि यह पहले से ही व्यवस्थित है फिर भी यह खाली है या नहीं, इसलिए यह $ @ का विस्तार करेगा , लेकिन आप "" के साथ $ {1: + "$ @"} का उपयोग करते हैं, यह $@किसी भी अधिक विस्तार नहीं करेगा ।


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