Vreau ca utilizatorul să fie solicitat cu o întrebare și apoi să furnizeze răspunsul, care va fi stocat sub o variabilă numită i, apoi dacă răspunsul (care este un fișier) există și se poate scrie, îl citește și agită lucrurile din fișier și scrie aceste lucruri într-unul nou. Dacă fișierul nu există sau utilizatorul nu are suficiente permisiuni pentru fișierul respectiv, atunci se va solicita un avertisment, programul va dormi 3 secunde și buclele vor începe din nou. De ce nu funcționează? Avertismentul pur și simplu nu va dispărea, nici bucla nu va continua.
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ăspuns
Aveți erori de sintaxă și logice.
$a=true
este doar un șir, NU o operațiune de comparație. Separați-vă cu spații, astfel încât comparația să aibă loc: "$a" = true
.
Cu acea funcționare, bucla câștigată nu va fi introdusă deloc, pe măsură ce setați a=false
în avans.
TREBUIE să intri în buclă, nu vei putea ieși, deoarece a
nu este niciodată setat la orice altceva decât true
și nici nu este prevăzut un alt mecanism de ieșire (de ex. break
).
Răspuns
După cum au subliniat alții, aveți erori logice și erori de sintaxă în cod. site-ul ShellCheck este bun pentru eliminarea erorilor de sintaxă.
Iată ideea mea. Am două versiuni ale codului . Primul (pe care îl prefer) nu are interacțiune cu utilizatorul, dar ia un nume de cale pe linia de comandă. Al doilea cere interactiv un nume de cale.
Motivul pentru care primul nu solicită interactiv un calea este că nu prea are nicio diferență dacă utilizatorul scriptului scrie calea pe linia de comandă sau la promptul scriptului dvs. și dacă solicitarea scriptului pentru calea respectivă o descalifică din a fi utilizată de ex. un job cron sau oriunde altundeva unde este posibil să nu existe un terminal atașat.
#!/bin/sh pathname=$1 if ! grep "pattern" <$pathname >i2; then echo "Something is wrong" >&2 fi
echo
de mai sus va fi executat când
- fișierul din
$pathname
nu poate fi citit sau - fișierul
i2
nu se poate scrie sau - modelul nu a fost găsit în
$pathname
(acest lucru este diferit de codul dvs., dar vedeți mai jos) .
Mesajul de eroare este scris în eroare standard, așa cum este obișnuit cu mesajele de diagnosticare în general.
Cu solicitare interactivă și întârziere:
#!/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
Aici avem o buclă infinită care citește de la utilizator și iese din buclă dacă apelul grep
a mers bine. Dacă grep
a eșuat din orice motiv (unul dintre cele trei motive de mai sus), calea este solicitată din nou.
Ambele bucăți de cod cu o separare test pentru un fișier lizibil (grep
este permis să eșueze prin faptul că nu găsește nimic sau nu poate scrie în fișierul său de ieșire.
Mai întâi, fișierul non-interactiv versiune:
#!/bin/sh pathname=$1 if [ ! -r "$pathname" ]; then echo "Something is wrong" >&2 fi grep "pattern" <$pathname >i2
Apoi versiunea interactivă:
#!/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
Sau, o versiune interactivă unde bucla se referă doar la introducerea și validarea utilizatorului:
#!/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
Răspuns
Încercați să utilizați pur și simplu pauză pentru a opri o buclă infinită astfel:
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
Locurile modificate au comentarii cu descriere.
grep <$i >i2
mai degrabă decâtcat
. De asemenea, citați extensiile variabile acolo unde este necesar, ca în test .