Comment boucler une instruction if dans bash?

Je veux que lutilisateur soit invité avec une question, puis fournisse la réponse, qui sera stockée sous une variable nommée i, alors si la réponse (qui est un fichier) existe et est accessible en écriture, il le lit et greps des éléments dans le fichier et les écrit dans un nouveau. Si le fichier n’existe pas ou si l’utilisateur n’a pas suffisamment d’autorisations sur ce fichier, un avertissement s’affiche, le programme se met en veille pendant 3 secondes et les boucles recommencent. Pourquoi cela ne fonctionne-t-il pas? Lavertissement ne disparaîtra tout simplement pas, et la boucle ne continuera pas non plus.

echo "$(tput setaf 4) Tell me where the file is:" printf "\n" a=false while [ $a=true ]; do read i if [ -w $i ] then cat $i | grep stuff > i2 else a=true printf "Oh something is wrong, try again!" sleep 3 fi done 

Réponse

Vous avez des erreurs de syntaxe et de logique.

Le $a=true est juste une chaîne, PAS une opération de comparaison. Séparez-les par des espaces pour que la comparaison ait lieu: "$a" = true.

Avec cela, la boucle ne sera pas du tout entrée, car vous définissez a=false davance.

DEVRIEZ-VOUS enfin entrer dans la boucle, vous ne pourrez « pas sortir, car a ne lest jamais défini sur autre chose que true, et aucun autre mécanisme de sortie (par exemple break) nest fourni.

Réponse

Comme dautres lont souligné, vous avez des erreurs logiques et des erreurs de syntaxe dans votre code. Le site ShellCheck est bon pour éliminer les erreurs de syntaxe.

Voici mon avis à ce sujet. Jai deux versions du code . Le premier (que je préfère) na pas dinteraction avec lutilisateur mais prend un chemin sur la ligne de commande. Le second demande interactivement un chemin.

La raison pour laquelle le premier ne demande pas de manière interactive un chemin est que cela fait peu de différence si lutilisateur du script écrit le chemin sur la ligne de commande ou à linvite de votre script, et avoir linvite de script pour le chemin le disqualifie dêtre utilisé par exemple. une tâche cron ou nimporte où ailleurs où il ny a pas de terminal attaché.

#!/bin/sh pathname=$1 if ! grep "pattern" <$pathname >i2; then echo "Something is wrong" >&2 fi 

Le echo ci-dessus sera exécuté lorsque

  • le fichier dans $pathname ne peut « pas être lu, ou
  • le fichier i2 ne peut pas être écrit ou
  • le modèle n’a pas été trouvé dans $pathname (ceci est différent de votre code, mais voir ci-dessous) .

Le message derreur est écrit en erreur standard, tout comme la coutume avec les messages de diagnostic en général.

Avec invite et délai interactifs:

#!/bin/bash while true; do read -r -p "Pathname: " pathname if grep "pattern" <$pathname >i2; then break fi echo "Something is wrong" >&2 sleep 3 done 

Ici, nous avons une boucle infinie qui lit lutilisateur et sort de la boucle si lappel grep sest déroulé correctement. Si grep a échoué pour une raison quelconque (lune des trois raisons ci-dessus), le chemin est à nouveau invité.


Les deux morceaux de code avec un tester pour un fichier lisible (le grep est autorisé à échouer en ne trouvant rien ou en ne pouvant pas écrire dans son fichier de sortie.

Dabord le non-interactif version:

#!/bin/sh pathname=$1 if [ ! -r "$pathname" ]; then echo "Something is wrong" >&2 fi grep "pattern" <$pathname >i2 

Puis la version interactive:

#!/bin/bash while true; do read -r -p "Pathname: " pathname if [ -r "$pathname" ]; then grep "pattern" <$pathname >i2 break fi echo "Something is wrong" >&2 sleep 3 done 

Ou, une version interactive où la boucle ne traite que de la saisie et de la validation de lutilisateur:

#!/bin/bash while true; do read -r -p "Pathname: " pathname [ -r "$pathname" ] && break echo "Something is wrong" >&2 sleep 3 done grep "pattern" <$pathname >i2 

Answer

Essayez dutiliser simplement break pour arrêter la boucle infinie comme ceci:

echo "$(tput setaf 4) Tell me where the file is:" echo # This prints empty line like printf "\n" while true; do # "while true" or "while :" is infinite loop read i if [ -r $i ] # You probably mean -r (readable) and not -w (writable) then cat $i | grep stuff > i2 break # "break" ends loop else echo -n "Oh something is wrong, try again!" # "echo -n" means print without newline character sleep 3 fi done 

Les lieux modifiés ont des commentaires avec une description.

Commentaires

  • grep <$i >i2 plutôt que cat. De plus, citez les extensions de variables si nécessaire, comme dans le test .

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *