web-dev-qa-db-fra.com

Comment extraire l'état de sortie d'une commande dans une variable?

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

J'essaie d'obtenir un statut de sortie de l'expression grep 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?

15
omri gilhar

Votre commande,

check=grep -ci 'text' file.sh

sera interprété par le shell comme "exécutez la commande -ci avec les arguments text et file.sh, et définissez la variable check sur la valeur grep dans 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 variable check:

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

(noter la -q, il demande à grep de ne rien afficher et de quitter dès que quelque chose correspond; nous ne sommes pas vraiment intéressés par ce qui correspond ici)

Ou, si vous voulez juste "faire des choses" quand le motif est pas trouvé:

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

Sauvegarde $? dans une autre variable n'est nécessaire que si vous devez l'utiliser ultérieurement, lorsque la valeur dans $? a été remplacé, 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 écrasé 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.

27
Kusalananda

Vous avez dit à bash de définir la variable check=grep dans l'environnement, il passe à la commande

-ci 'text' file.sh

mais ci n'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)

Maintenant $check doit être 0 s'il n'y a pas de correspondance, ou positif s'il y en a.

4
Monty Harder

Votre question n'est pas claire, mais d'après le code que vous avez soumis, il semble que vous souhaitiez que la variable check stocke l'état de sortie de la commande grep. Pour ce faire, exécutez

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

Lors de l'exécution d'une commande à partir d'un shell, son état de sortie est rendu disponible via le paramètre spécial du shell, $?.

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

Étant donné que 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érerais Lhunath et GreyCat’s Bash Guide .

4
Anthony Geoghegan

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
1
Miati

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 avoir exécuté la commande, comme indiqué ci-dessous:

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