Comment extrait-on l'état de sortie d'une commande dans une variable?

14

J'ai commencé à apprendre le Bash il y a quelques jours.

J'essaie d'obtenir un statut de sortie d' grepexpression dans une variable comme celle-ci:

check=grep -ci 'text' file.sh

et la sortie que j'ai obtenue est

No command '-ic' found

Dois-je le faire avec une commande pipe?

omri gilhar
la source
6
Pour l'état de sortie, vous pouvez examiner $?juste après la fin de la commande.
coffeMug
et vous pouvez examiner le tableau PIPESTATUS si vous voulez l'état d'une des commandes dans un pipeline.
cas

Réponses:

26

Votre commande,

check=grep -ci 'text' file.sh

sera interprété par le shell comme "exécutez la commande -ciavec les arguments textet file.sh, et définissez la variable checksur la valeur grepdans son environnement".


Le shell stocke la valeur de sortie de la dernière commande exécutée dans la variable ?. Vous pouvez affecter sa valeur à l'une de vos propres variables comme ceci:

grep -i 'PATTERN' file
check=$?

Si vous souhaitez agir sur cette valeur, vous pouvez soit utiliser votre checkvariable:

if [ "$check" -eq 0 ]; then
    # do things for success
else
    # do other things for failure
fi

ou vous pouvez sauter en utilisant une variable distincte et avoir à inspecter $?tous ensemble:

if grep -q -i 'pattern' file; then
  # do things (pattern was found)
else
  # do other things (pattern was not found)
fi

(notez le -q, il indique grepde ne rien produire et de sortir dès que quelque chose correspond; nous ne sommes pas vraiment intéressés par ce qui correspond ici)

Ou, si vous voulez simplement "faire des choses" lorsque le motif n'est pas trouvé:

if ! grep -q -i 'pattern' file; then
  # do things (pattern was not found)
fi

L'enregistrement $?dans une autre variable n'est nécessaire que si vous devez l'utiliser plus tard, lorsque la valeur de $?a été remplacée, comme dans

mkdir "$dir"
err=$?

if [ "$err" -ne 0 ] && [ ! -d "$dir" ]; then
    printf 'Error creating %s (error code %d)\n' "$dir" "$err" >&2
    exit "$err"
fi

Dans l'extrait de code ci-dessus, $?sera remplacé par le résultat du [ "$err" -ne 0 ] && [ ! -d "$dir" ]test. L'enregistrer ici n'est vraiment nécessaire que si nous devons l'afficher et l'utiliser avec exit.

Kusalananda
la source
4

Votre question n'est pas claire mais en fonction du code que vous avez soumis, il semble que vous souhaitiez que la variable checkstocke l'état de sortie de la grepcommande. Pour ce faire, exécutez

grep -ci 'text' file.sh
check=$?

Lors de l' exécution d' une commande à partir d' une coque, de son état de sortie est mis à disposition par l'intermédiaire du paramètre d'enveloppe spéciale $?.

Ceci est documenté par POSIX (la norme pour les systèmes d'exploitation de type Unix) dans sa spécification pour le shell et l'implémentation de Bash est documentée sous Paramètres spéciaux .

Puisque vous êtes un nouvel apprenant, je vous recommande fortement de commencer par un bon livre et / ou un didacticiel en ligne pour obtenir les bases. Les recommandations de ressources externes sont déconseillées sur les sites Stack Exchange mais je suggère le guide Bash de Lhunath et GreyCat .

Anthony Geoghegan
la source
4

Vous avez dit à bash de définir la variable check=grepdans l'environnement qu'elle transmet à la commande

-ci 'text' file.sh

mais cin'existe pas.

Je pense que vous vouliez inclure cette commande entre des tiques inverses ou entre parenthèses précédées d'un signe dollar, l'une ou l'autre affectant le nombre de lignes sur lesquelles le `` texte '' a été trouvé (en respectant la casse) dans le fichier:

check=`grep -ci 'text' file.sh`

check=$(grep -ci 'text' file.sh)

Devrait maintenant $checkêtre 0 s'il n'y a pas de correspondance, ou positif s'il y avait des correspondances.

Monty Harder
la source
1

Vous ne savez pas pourquoi utiliser -c lors de la vérification de la sortie? Il est utilisé pour vérifier combien de fois quelque chose est apparié - pas si c'est réussi ou non.

   -c, --count
          Suppress normal output; instead print a count of matching  lines
          for  each  input  file.  With the -v, --invert-match option (see
          below), count non-matching lines.  (-c is specified by POSIX.)

mais dans cet exemple

check="$(grep --silent -i 'text' file.sh; echo $?)"

Il ne produit rien sauf un code de sortie, qui est ensuite répété. Il s'agit de la sortie utilisée par la vérification des variables. Je le préfère aussi car c'est une seule ligne.

Vous pouvez remplacer --silent par -q. Je l'utilise car vous n'êtes pas intéressé par la sortie grep, que cela fonctionne ou non.

   -q, --quiet, --silent
          Quiet;  do  not  write  anything  to  standard   output.    Exit
          immediately  with  zero status if any match is found, even if an
          error was detected.  Also see the -s  or  --no-messages  option.
          (-q is specified by POSIX.)

$ check=$(echo test | grep -qi test; echo $?) # check variable is now set
$ echo $check
0
$ check=$(echo null | grep -qi test; echo $?)
$ echo $check
1
Miati
la source
1

La manière correcte d'affecter la sortie de la commande grep à une variable est comme mentionné @ monty-hard:

check=`grep -ci 'text' file.sh`
check=$(grep -ci 'text' file.sh)

Bien que pour affecter le statut de sortie de cette commande à une variable, vous devez utiliser le paramètre shell $?juste après l'exécution de la commande, comme indiqué ci-dessous:

grep -ci 'text' file.sh
check=$?
echo $check
Curieuse
la source