शेल स्क्रिप्ट में फ़ंक्शन से रिटर्निंग वैल्यू


126

मैं शेल स्क्रिप्ट में एक फ़ंक्शन से मान वापस करना चाहता हूं। शायद मुझे वाक्य रचना याद आ रही है। मैंने वैश्विक चर का उपयोग करने की कोशिश की। लेकिन वह भी काम नहीं कर रहा है। कोड है:

lockdir="somedir"
test() {
    retval=""

    if mkdir "$lockdir"
        then    # Directory did not exist, but it was created successfully
            echo >&2 "successfully acquired lock: $lockdir"
            retval="true"
        else
            echo >&2 "cannot acquire lock, giving up on $lockdir"
            retval="false"
    fi
    return retval
}


retval=test()
if [ "$retval" == "true" ]
    then
        echo "directory not created"
    else
        echo "directory already created"
fi

आपके प्रश्न से संबंधित नहीं है, लेकिन फिर भी ... यदि आप एक ताला पाने की कोशिश कर रहे हैं तो आप "लॉकफ़ाइल" कमांड का उपयोग कर सकते हैं।
विक्टर हेर्रिज

जवाबों:


277

एक बैश फ़ंक्शन सीधे एक स्ट्रिंग वापस नहीं कर सकता जैसे आप इसे चाहते हैं। आप तीन काम कर सकते हैं:

  1. एक स्ट्रिंग गूंज
  2. बाहर निकलने की स्थिति लौटाएं, जो एक संख्या है, न कि एक स्ट्रिंग
  3. एक चर साझा करें

यह कुछ अन्य गोले के लिए भी सही है।

यहाँ उन विकल्पों में से प्रत्येक को कैसे करना है:

1. प्रतिध्वनि

lockdir="somedir"
testlock(){
    retval=""
    if mkdir "$lockdir"
    then # Directory did not exist, but it was created successfully
         echo >&2 "successfully acquired lock: $lockdir"
         retval="true"
    else
         echo >&2 "cannot acquire lock, giving up on $lockdir"
         retval="false"
    fi
    echo "$retval"
}

retval=$( testlock )
if [ "$retval" == "true" ]
then
     echo "directory not created"
else
     echo "directory already created"
fi

2. वापसी की स्थिति

lockdir="somedir"
testlock(){
    if mkdir "$lockdir"
    then # Directory did not exist, but was created successfully
         echo >&2 "successfully acquired lock: $lockdir"
         retval=0
    else
         echo >&2 "cannot acquire lock, giving up on $lockdir"
         retval=1
    fi
    return "$retval"
}

testlock
retval=$?
if [ "$retval" == 0 ]
then
     echo "directory not created"
else
     echo "directory already created"
fi

3. शेयर चर

lockdir="somedir"
retval=-1
testlock(){
    if mkdir "$lockdir"
    then # Directory did not exist, but it was created successfully
         echo >&2 "successfully acquired lock: $lockdir"
         retval=0
    else
         echo >&2 "cannot acquire lock, giving up on $lockdir"
         retval=1
    fi
}

testlock
if [ "$retval" == 0 ]
then
     echo "directory not created"
else
     echo "directory already created"
fi

2
functionएक बश फ़ंक्शन को परिभाषित करने के लिए एक कीवर्ड का उपयोग न करें । यह इसे कम पोर्टेबल बना देगा। उसे निकाल रहे हैं।
डिमर

2
आपके तीसरे उदाहरण में, प्रतिधारण एक पर्यावरण चर नहीं है। यह एक शेल चर है। यदि आप इसे निर्यात करते हैं तो यह केवल एक पर्यावरण चर बन जाएगा। शायद तीसरे उदाहरण का शीर्षक "पर्यावरण चर" के बजाय "वैश्विक चर" होना चाहिए।
विलियम पर्ससेल

4
दूसरे उदाहरण में, $ से असाइन करने के बजाय ?, "अगर टेस्टलॉक है, तो यह लिखना अधिक मुहावरेदार है ..."
विलियम पर्सेल

@WilliamPursell मैंने गलत 'पर्यावरण' शब्द को हटा दिया है। चलो रखते हैं "$?" शैक्षणिक उद्देश्य के लिए। मैंने विकी समुदाय को सक्षम किया है, इसलिए आप उत्तर को सुधारने के लिए सभी स्वतंत्र हैं; ;-)
ओलिब्रे

1
@ मेन्यूअल जोर्डन, फंक्शंस केवल एग्जिट कोड और> और 2 लॉग को स्टोडर पर वापस कर सकते हैं, इसलिए, अंतिम गूंज को स्टडआउट को लिखा जाता है, इसलिए, कॉलिंग फ़ंक्शन केवल स्टैडआउट को कैप्चर करता है और स्टैडर को नहीं। निष्पादन को एकल थ्रेडेड माना जाता है, एक बेहतर विकल्प TEST_LOCK_STATUS = "" बाहर की विधि की तरह एक कस्टम चर विशिष्ट बनाए रखना है जिसे कोई भी टेस्टलॉक कॉल करने के बाद उपयोग कर सकता है और विधि के शुरू होने पर इसे हर बार रीसेट कर सकता है
किस्ना

16

आप बहुत कठिन तरीके से काम कर रहे हैं। आपकी पूरी स्क्रिप्ट होनी चाहिए:

if mkdir "$lockdir" 2> /dev/null; then 
  echo lock acquired
else
  echo could not acquire lock >&2
fi

लेकिन यहां तक ​​कि शायद बहुत अधिक क्रिया है। मैं इसे कोडित करूंगा:

mkdir "$lockdir" || exit 1

लेकिन परिणामी त्रुटि संदेश थोड़ा अस्पष्ट है।


1
लापता त्रुटि संदेश को ठीक करना काफी आसान है, भले ही यह थोड़ा अधिक क्रिया है: mkdir "$lockdir" || { echo "could not create lock dir" >&2 ; exit 1 ; }(नोट ;बंद करने से पहले घुंघराले ब्रेस)। इसके अलावा, मैं अक्सर एक असफल फ़ंक्शन को परिभाषित करता हूं जो एक वैकल्पिक संदेश पैरामीटर लेता है जो इसे stderr को प्रिंट करता है और फिर रिटर्न कोड 1 से बाहर निकलता है, जिससे मुझे अधिक पठनीय का उपयोग करने में सक्षम होता है mkdir "$lockdir" || fail "could not create lock dir"
ब्लबरडाइब्लड

@blubberdiblub: लेकिन विफल फ़ंक्शन "वर्तमान" फ़ंक्शन या स्क्रिप्ट से बाहर नहीं निकल सकता, क्या यह कर सकता है? इसलिए cmd || fail "error msg" || return 1यदि आप ऐसा करना चाहते हैं, तो आपको इसका उपयोग करना होगा?
मैक्स

@ मोम वर्तमान फ़ंक्शन नहीं है, यह सही है। लेकिन यह वर्तमान स्क्रिप्ट से बाहर निकल जाएगा, जब तक कि आप इसे एक कमांड के रूप में कहते हैं और इसे स्रोत नहीं करते हैं। मैं आमतौर पर इस तरह के एक failसमारोह के बारे में सोचता हूं जो केवल घातक स्थितियों के लिए उपयोग किया जाता है।
ब्लबरडाइबुल जुब

12

यदि यह सिर्फ एक सही / गलत परीक्षा है, तो return 0सफलता के लिए, और return 1विफलता के लिए आपका कार्य है । परीक्षण तब होगा:

if function_name; then
  do something
else
  error condition
fi

ठीक वही जो मेरे द्वारा खोजा जा रहा था।
सैमुअल

क्या इस नोटेशन के साथ-साथ पैरामीटर किए गए कार्यों के लिए उपयोग करने का कोई तरीका है?
एलेक्स

@alex क्या आप इसका उदाहरण दे सकते हैं कि "पैरामीटर किए गए फ़ंक्शन" से आपका क्या मतलब है?
ग्लेन जैकमैन

'myCopyFunc $ {SOURCE} $ {DEST}', सफलता पर 0 वापसी। जैसे इस अंक में: stackoverflow.com/questions/6212219/…
एलेक्स

हाँ, यह पूरी तरह से ठीक है
ग्लेन जैकमैन

2

मुझे लगता है कि असफल (ग्लेन जैकमैन) के लिए succ / 1 के लिए 0 लौटाना और ऑलिब्रे का स्पष्ट और व्याख्यात्मक उत्तर यह सब कहता है; केवल उन मामलों के लिए एक प्रकार का "कॉम्बो" दृष्टिकोण का उल्लेख करने के लिए जहां परिणाम द्विआधारी नहीं हैं और आप परिणाम को "गूंज" के बजाय एक चर सेट करना पसंद करेंगे (उदाहरण के लिए यदि आपका कार्य ALSO लगता है कि कुछ गूंज है, तो यह दृष्टिकोण होगा काम नहीं)। फिर क्या? (नीचे बॉर्न शेल है)

# Syntax _w (wrapReturn)
# arg1 : method to wrap
# arg2 : variable to set
_w(){
eval $1
read $2 <<EOF
$?
EOF
eval $2=\$$2
}

जैसे (हां, उदाहरण कुछ मूर्खतापूर्ण है, यह सिर्फ एक उदाहरण है)

getDay(){
  d=`date '+%d'`
  [ $d -gt 255 ] && echo "Oh no a return value is 0-255!" && BAIL=0 # this will of course never happen, it's just to clarify the nature of returns
  return $d
}

dayzToSalary(){
  daysLeft=0
  if [ $1 -lt 26 ]; then 
      daysLeft=`expr 25 - $1`
  else
     lastDayInMonth=`date -d "`date +%Y%m01` +1 month -1 day" +%d`
     rest=`expr $lastDayInMonth - 25`
     daysLeft=`expr 25 + $rest`
  fi
  echo "Mate, it's another $daysLeft days.."
}

# main
_w getDay DAY # call getDay, save the result in the DAY variable
dayzToSalary $DAY

1

मामले में आप एक समारोह में पारित करने के लिए कुछ मापदंडों और बदले में एक मूल्य चाहते हैं। यहां मैं एक फ़ंक्शन के तर्क के रूप में "12345" पास कर रहा हूं और रिटर्निंग वेरिएबल XYZ को प्रोसेस करने के बाद जो VALUE को सौंपा जाएगा

#!/bin/bash
getValue()
{
    ABC=$1
    XYZ="something"$ABC
    echo $XYZ
}


VALUE=$( getValue "12345" )
echo $VALUE

आउटपुट:

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