Come faccio a eseguire il loop di unistruzione if in bash?

Desidero che allutente venga richiesta una domanda e quindi fornisca la risposta, che verrà memorizzata in una variabile denominata i, quindi se la risposta (che è un file) esiste ed è scrivibile, lo legge e raccoglie le cose allinterno del file e le scrive in uno nuovo. Se il file non esiste o lutente non dispone di autorizzazioni sufficienti su quel file, viene richiesto un avviso, il programma si ferma per 3 secondi e il ciclo ricomincia. Perché non funziona? Lavvertimento semplicemente non sparirà, né il ciclo continuerà.

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 

Risposta

Hai errori di sintassi ed errori logici.

$a=true è solo una stringa, NON unoperazione di confronto. Separare con spazi in modo che il confronto abbia luogo: "$a" = true.

Con questo funzionamento, il ciclo non verrà affatto inserito, poiché imposti a=false in anticipo.

DOVREBBE finalmente entrare nel circuito, non potrai uscire, poiché a non lo è mai impostato su qualsiasi cosa tranne true, né viene fornito un altro meccanismo di uscita (ad es. break).

Risposta

Come altri hanno sottolineato, hai errori logici ed errori di sintassi nel tuo codice. Il sito ShellCheck è utile per eliminare gli errori di sintassi.

Ecco la mia opinione su questo. Ho due versioni del codice . Il primo (che preferisco) non ha interazioni con lutente ma accetta un percorso sulla riga di comando. Il secondo chiede interattivamente un percorso.

Il motivo per cui il primo non richiede interattivamente un pathname è che fa poca differenza se lutente dello script scrive il pathname sulla riga di comando o al prompt del tuo script, e avere il prompt dello script per il pathname lo squalifica dalluso ad es. un cron job o altrove in cui potrebbe non essere collegato un terminale.

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

Il echo sopra sarà eseguito quando

  • il file in $pathname non può “essere letto, oppure
  • il file i2 non è possibile scrivere o
  • il pattern non è stato trovato in $pathname (questo è diverso dal tuo codice, ma vedi sotto) .

Il messaggio di errore viene scritto in errore standard, come è consuetudine con i messaggi diagnostici in generale.

Con prompt e ritardo interattivi:

#!/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 

Qui abbiamo un ciclo infinito che legge dallutente ed esce dal ciclo se la chiamata grep è andata a buon fine. Se grep non è riuscito per qualsiasi motivo (uno dei tre motivi sopra), viene richiesto di nuovo il nome del percorso.


Entrambe le parti di codice con un test per un file leggibile (il grep può fallire se non trova nulla o non è in grado di scrivere nel suo file di output.

Prima il non interattivo versione:

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

Quindi la versione interattiva:

#!/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 

Oppure, una versione interattiva dove il ciclo si occupa solo dellinput e della convalida dellutente:

#!/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 

Risposta

Prova a utilizzare semplicemente interruzione per interrompere il ciclo infinito in questo modo:

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 

I luoghi modificati hanno commenti con descrizione.

Commenti

  • grep <$i >i2 piuttosto che cat. Inoltre, cita le espansioni delle variabili dove necessario, come nel test .

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *