Ik wil dat de gebruiker een vraag krijgt en vervolgens het antwoord geeft, dat wordt opgeslagen onder een variabele met de naam i, en als het antwoord (die is een bestand) bestaat en is beschrijfbaar, het leest het en grijpt dingen in het bestand en schrijft die dingen naar een nieuw bestand. Als het bestand niet bestaat of de gebruiker niet genoeg rechten heeft voor dat bestand, wordt er een waarschuwing weergegeven, slaapt het programma 3 seconden en beginnen de lussen opnieuw. Waarom werkt het niet? De waarschuwing gaat gewoon niet weg, en de lus blijft ook niet doorgaan.
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
Antwoord
Je hebt syntaxis en logische fouten.
De $a=true
is slechts een tekenreeks, GEEN vergelijkingsoperatie. Scheid met spaties zodat de vergelijking plaatsvindt: "$a" = true
.
Als dat werkt, wordt de lus helemaal niet ingevoerd, aangezien je a=false
vooraf.
ALS u eindelijk in de lus terechtkomt, kunt u “niet afsluiten, aangezien a
nooit ingesteld op iets anders dan true
, noch is er een ander exit-mechanisme (bijv. break
) voorzien.
Antwoord
Zoals anderen hebben opgemerkt, heb je logische fouten en syntaxisfouten in je code. De ShellCheck-site is goed voor het verwijderen van syntaxisfouten.
Hier is mijn mening hierover. Ik heb twee versies van de code . De eerste (waar ik de voorkeur aan geef) heeft geen gebruikersinteractie maar neemt een padnaam op de opdrachtregel. De tweede vraagt interactief om een padnaam.
De reden dat de eerste niet interactief om een padnaam is dat het weinig verschil maakt als de gebruiker van het script de padnaam op de opdrachtregel of op de prompt van uw script schrijft, en als de scriptprompt voor de padnaam wordt gebruikt, wordt deze uitgesloten van gebruik door bijv. een cron-taak of ergens anders waar mogelijk geen terminal is aangesloten.
#!/bin/sh pathname=$1 if ! grep "pattern" <$pathname >i2; then echo "Something is wrong" >&2 fi
De echo
hierboven zal zijn uitgevoerd wanneer
- het bestand in
$pathname
“niet kan worden gelezen, of - het bestand
i2
kan “niet worden geschreven, of - het patroon is niet gevonden in
$pathname
(dit verschilt van uw code, maar zie hieronder) .
Het foutbericht wordt geschreven naar standaardfout, zoals gebruikelijk is bij diagnostische berichten in het algemeen.
Met interactieve prompts en vertraging:
#!/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
Hier hebben we een oneindige lus die van de gebruiker wordt gelezen en uit de lus komt als de grep
-aanroep goed ging. Als grep
om welke reden dan ook mislukt (een van de drie bovenstaande redenen), wordt de padnaam opnieuw gevraagd.
Beide stukjes code met een afzonderlijke test voor een leesbaar bestand (de grep
mag mislukken door niets te vinden of niet te kunnen schrijven naar het uitvoerbestand.
Ten eerste de niet-interactieve version:
#!/bin/sh pathname=$1 if [ ! -r "$pathname" ]; then echo "Something is wrong" >&2 fi grep "pattern" <$pathname >i2
Dan de interactieve versie:
#!/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
Of, een interactieve versie waarbij de lus alleen betrekking heeft op gebruikersinvoer en validatie:
#!/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
Antwoord
Probeer gewoon break te gebruiken om de oneindige lus als volgt te stoppen:
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
Gewijzigde plaatsen hebben opmerkingen met een beschrijving.
grep <$i >i2
in plaats van decat
. Citeer ook uitbreidingen van variabelen waar nodig, zoals in de test .