A Bash kétféle ciklust ismer:
Egy lista elemein való iteráláshoz a for ciklust használjuk.
for varname in words; do COMMANDS; done
A words szófelbontással és fájlnév-kiterjesztéssel bővül (ezekről az idézés fogalmában tanultunk).
Minden szó sorban hozzárendelődik a varname változóhoz, és a COMMANDS parancsok végrehajtódnak.
Íme néhány példa, amelyek megmutatják, mikor lehet hasznos a for ciklus
Hajts végre néhány parancsot egy fájlcsoporton.
# source all the bash library files in the current directory
for file in ./*.bash; do
source "$file"
done
Hajts végre valamilyen parancsot egy szkript vagy függvény minden paraméterén.
for arg in "$@"; do
echo "argument: ${arg}"
done
Hajts végre valamilyen parancsot egy parancs kimenetének minden whitespace-szel elválasztott szavára.
for i in $(seq 10); do
echo "${i} squared is $((i * i))"
done
Később látni fogunk néhány figyelmeztetést ezzel a stílussal kapcsolatban.
A Bash-nek valóban van aritmetikai ciklusa. Ez némileg ismerős lesz más programozási nyelvekből.
for ((INITIALIZATION; CONDITION; INCREMENT)); do COMMANDS; done
A dupla zárójel a Bash-ben aritmetikai kontextust jelent (a Bash-aritmetikáról később egy másik fogalomban lesz szó).
A fenti, seq-et használó példa így írható fel:
for ((i = 1; i <= 10; i++)); do
echo "${i} squared is $((i * i))"
done
Ez egy gyakran látott antiminta: a cat kimenetén iterálunk.
for line in $(cat some.file); do
do_something_with "$line"
done
Ez két szempontból is hibás.
Ahogy az idézés fogalmában tanultuk, a szófelbontás az IFS változóval szabályozható, a fájlnév-kiterjesztés pedig kikapcsolható.
De ez általában törékeny megoldás.
A for nem megfelelő módszer egy fájl sorainak bejárására.
A fájl beolvasásának idiomatikus módja a while ciklus.
A while segítségével parancsok sorozatát ismételheted amíg valamilyen feltétel igaz.
while CONDITION_COMMANDS; do COMMANDS; done
Ahogy az if esetében is (ahogy a feltételes elágazások fogalmában tanultuk), nincs különleges szintaxis a CONDITION_COMMANDS számára.
A parancslista kilépési állapota dönti el, hogy „igaz” vagy „hamis”.
A break parancs kilép a ciklusból.
A vezérlés a ciklus done lezárója utáni paranccsal folytatódik.
A continue parancs a ciklus következő iterációjára ugrik.
Ahogy említettük, a fájl beolvasásának idiomatikus módja a while ciklus.
while IFS= read -r line; do
do_something_with "$line"
done < some.file
A fájl tartalma a < átirányítással lesz a ciklus bemenete.
A read parancs „igaz” értékkel tér vissza, ha egy teljes sort tud olvasni a bemenetéről.
Amikor a bemenet elfogy, vagy ha az utolsó sor végén nincs záró sortörés, akkor a read „hamis” értékkel tér vissza.
A valóban idiomatikus módja egy fájl sorai beolvasásának, még akkor is, ha az utolsó sor nem végződik sortöréssel:
while IFS= read -r line || [[ -n "$line" ]]; do ...
A -r kapcsoló azt mondja a read-nek, hogy ne helyettesítse a backslash-szekvenciákat: a backslash egyszerű karakter.
Az IFS= csak a read parancs időtartamára rendeli az üres stringet az IFS-hez.
Ez átmenetileg kikapcsolja a szófelbontást, így a bejövő szövegsor elején vagy végén lévő whitespace megmarad.
Az until szerkezet parancsok sorozatát ismétli, amíg valamilyen feltétel hamis.
A ciklus addig ismétlődik, amíg a feltétel igazzá nem válik.
until CONDITION_COMMANDS; do COMMANDS; done
Ritka az until használata.
Gyakoribb a „while not” ciklus használata.
while ! CONDITION_COMANDS; do ...
Néha örökké szeretnél ciklust futtatni. Íme két módszer erre.
egy while ciklus olyan feltétellel, amelynek kilépési állapota mindig sikeres
while true; do ...
egy aritmetikai for ciklus üres kifejezésekkel
for ((;;)); do ...
Nincs külön do-while szerkezet, de ugyanezt a hatást elérheted:
while true; do
COMMANDS
if END_CONDITION; then
break
fi
done