web-dev-qa-db-fra.com

Renvoi de la valeur de la fonction appelée dans un script Shell

Je veux renvoyer la valeur d'une fonction appelée dans un script Shell. Peut-être me manque la syntaxe. J'ai essayé d'utiliser les variables globales. Mais cela ne fonctionne pas non plus. Le code est:

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
110
Mridul Vishal

Une fonction Bash ne peut pas retourner une chaîne directement comme vous le souhaitez. Vous pouvez faire trois choses:

  1. Écho une ficelle
  2. Renvoie un statut de sortie, qui est un nombre, pas une chaîne
  3. Partager une variable

Cela est également vrai pour certains autres coquillages.

Voici comment faire chacune de ces options:

1. Cordes d'écho

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. Retourner le statut de sortie

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. Variable de partage

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
240
olibre

Vous travaillez trop dur. Votre script entier devrait être:

 if mkdir $ lockdir 2>/dev/null; puis 
 verrouillage d'écho acquis 
 sinon 
 écho n'a pas pu obtenir un verrouillage> & 2 
 fi 

mais même cela est probablement trop verbeux. Je le coderais:

 mkdir $ lockdir || sortie 1 

mais le message d'erreur qui en résulte est un peu obscur.

15
William Pursell

S'il ne s'agit que d'un test vrai/faux, définissez votre fonction return 0 pour réussir et return 1 pour un échec. Le test serait alors:

if function_name; then
  do something
else
  error condition
fi
12
glenn jackman

Je pense que retourner 0 pour succ/1 pour échec (Glenn Jackman) et que la réponse claire et explicite d’Olibre dit tout; juste pour mentionner une sorte d’approche "combo" dans les cas où les résultats ne sont pas binaires et que vous préférez définir une variable plutôt que "faire écho" un résultat (par exemple, si votre fonction doit AUSSI supposer faire écho à quelque chose, cette approche ne fonctionne pas). Quoi alors? (ci-dessous est Bourne Shell)

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

comme dans (ouais, l'exemple est un peu ridicule, c'est juste un exemple.)

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
2
Ola Aronsson