Hoi Ugurgazi,
Wat Overdenkamp schrijft klopt helemaal, dat is inderdaad wat je wil.
Maar de leukste manier om erachter te komen waarom het script nu niet goed werkt is Bash vertellen dat je precies wil zien wat er gebeurt. Dat doe je met de opdracht "set -x", wat zoiets betekent als show e
xecution. Het laat stap voor stap zien hoe je script uitgevoerd wordt. Je kan het aan het begin van je script zetten maar ook middenin je script vlak voor het punt waar het misgaat. Dan kun je vanaf waar het wel weer goed gaat "set +x" gebruiken om de show e
xecution weer uit te zetten. Hier is "set -x" genoeg. Er is ook nog "set -v" maar daar heb je hier niks aan.
Hier dan het script met een "set -x" opdracht om te debuggen, ik heb de commando's ingesprongen zoals zou moeten. Het is handig als je dat zelf kan, maar neem het voor nu gewoon even over. Met die ingesprongen stukken kun je goed de structuur van je script zien, vandaar.
#!/bin/bash
while true
do
getallinks=$((RANDOM/(32767/10)+1))
getalrechts=$((RANDOM/(32767/10)+1))
echo "Hoeveel is $getallinks x $getalrechts ?"
read -p "Antwoord: " antwoordleerling
antwoordjuiste=$((getallinks*getalrechts))
if test $antwoordleerling == $antwoordjuiste
then
echo "Goed zo! $getallinks x $getalrechts is inderdaad $antwoordjuiste."
else
while (( $antwoordleerling != $antwoordjuiste ))
do
set -x
echo "Fout! Probeer het nogmaals $getallinks x $getalrechts ="
read $getallinks x $getalrechts
set +x
done
fi
doneEn als ik dit probeer uit te voeren krijg ik:
laudaka@janeway2:~/bin/tafels$ ./tafelsommen.sh
Hoeveel is 6 x 4 ?
Antwoord: 24
Goed zo! 6 x 4 is inderdaad 24.
Hoeveel is 6 x 8 ?
Antwoord: 49
+ echo 'Fout! Probeer het nogmaals 6 x 8 ='
Fout! Probeer het nogmaals 6 x 8 =
+ read 6 x 8
48
./9tafelsom.sh: line 19: read: `6': not a valid identifier
+ set +x
+ echo 'Fout! Probeer het nogmaals 6 x 8 ='
Fout! Probeer het nogmaals 6 x 8 =
+ read 6 x 8
48
./9tafelsom.sh: line 19: read: `6': not a valid identifier
+ set +x
+ echo 'Fout! Probeer het nogmaals 6 x 8 ='
Fout! Probeer het nogmaals 6 x 8 =
+ read 6 x 8Wat gaat er mis? Die regel met "read $getallinks x $getalrechts" is inderdaad fout, die levert hier de regel "read 6 x 8" op. Er mist een "-p" om een boodschap te printen naar de terminal en dan zouden er nog aanhalingstekens nodig zijn om de tekst bij elkaar te houden die vlak na "-p" komt.
En er staat geen variabele waar "read" het antwoord in moet stoppen. Bash voert die regel gewoon als een kip zonder kop uit. In de variabele "getallinks" staat een "6" dus bash vult die 6 gewoon in op de regel. Maar als je geen "-p" hebt met een te printen boodschap dan verwacht "read" meteen de naam van een variabele waarin de invoer gestopt moet worden. En "6" is niet een geldige naam voor een variabele, variabelen moeten beginnen met een letter. De foutmelding zegt "read: `6': not a valid identifier". Een identifier is een naam voor een variabele, en "6" kan dus nooit de naam van een variabele zijn. Bash klaagt dus dat het onmogelijk is om iets in de variabele met de naam "6" te stoppen omdat "6" geen geldige naam is voor een variabele.
Als je de regel vervangt door:
read antwoordleerling
werkt het wel. Of uitgebreider, zoals Overdenkamp voorstelde:
read -p "Fout! Probeer het nogmaals $getallinks x $getalrechts = " antwoordleerling
Je kan ook de tekst die vraagt om het antwoord eerst met "echo" afdrukkken. En dan pas doe je de regel met de opdracht "read", dat leest makkelijker:
echo -n "Fout! Probeer het nogmaals $getallinks x $getalrechts = "
read antwoordleerling
Die "-n" bij echo voorkomt dat je een nieuwe regel krijgt na de tekst die je afdrukt. (Staat voor geen
newline.)
Dan hier nog eens het hele programma:
#!/bin/bash
while true
do
getallinks=$((RANDOM/(32767/10)+1))
getalrechts=$((RANDOM/(32767/10)+1))
echo -n "Hoeveel is $getallinks x $getalrechts ? "
read antwoordleerling
antwoordjuiste=$((getallinks*getalrechts))
if (( antwoordleerling == antwoordjuiste ))
then
echo "Goed zo! $getallinks x $getalrechts is inderdaad $antwoordjuiste."
else
while (( antwoordleerling != antwoordjuiste ))
do
echo -n "Fout! Probeer het nogmaals $getallinks x $getalrechts = "
read antwoordleerling
done
fi
done
Er zitten een paar kleine wijzigingen in. Er is één ding wat ik hierboven niet uitgelegd heb. Dat is de regel die eerst was:
if test $antwoordleerling == $antwoordjuiste
En die ik heb veranderd in:
if (( antwoordleerling == antwoordjuiste ))
Dit kan hetzelfde als bij de "while". Zelf schrijf ik het liever met "(( ... ))" met dubbele haakjes dus. Maar omdat het nogal verwarrend is dat je in hetzelfde programma zowel "$(( ... ))" gebruikt als "(( ... ))" had ik het expres niet gebruikt. De betekenis met en zonder die "$" is echt anders. Om het nog verwarrender te maken kun je bij "(( ... ))" opeens wel de inhoud van variabelen uitlezen zonder dat er ergens eerder op de regel een "$" staat. Hoewel het programma zou werken met die extra dollartekens, zijn die overbodig.
Vergelijk:
antwoordjuiste=$(( getallinks * getalrechts ))
if (( antwoordleerling == antwoordjuiste ))
Dat is wel genoeg voor vandaag.
Veel plezier, ik hoop dat het niet te moeilijk is en dat ik het niet te droog vertel.
Paulus/laudaka
@Overdenkamp. Ik zie dat ik niet de enige ben die probeert mensen over te halen om officiële documentatie te lezen. Unix/Linux/Ubuntu zal nooit meer hetzelfde zijn nu we Google hebben...