Скрипты на bash — Подводные камни в циклах bash
Сегодня я хотел бы рассказать о возможных подводных камнях и их обходе при написании скриптов на bash.
while;do : ;done
обычно я использую цикл while в случае когда требуется обработка строк разделенных пробелами (в отличии от for, см. ниже)
но это не единственное различие for и while в bash. приведу простой пример
Здесь я хотел бы обратить внимание на то, как распределятся процессы при выполнении кода, ветки основного процесса я помечу курсивом, а ветки потомка выделю жирным
echo -e 'test test\ntest2\ntest3 test3'|
while read a ;do
echo ==$a
exit
done
echo "the script finished $a"
таким образом становится понятно, что цикл выйдет напечатав
test test
, но переменная $a останется необновленной, к тому же exit в конце выйдет всего-лишь из цикла. поэтому последняя строка вывода будет
the script finished
попробуем написать скрипт основаный на while, который напечатает все строки а в конце получит в управление переменную заданную в теле цикла., так-же выведет было ли выполнение цикла вообще.
все гораздо проще чем кажется мы просто перенесем echo в дочерний процесс избавившись от перенаправления через pipe:
while read a ;do
echo ==$a
flag=1
done < <(echo -e 'test test\ntest2\ntest3 test3')
if [ $flag ] ;then echo "the script finished, loop completed $a" else
echo "the script finished, loop didn't started";
fi
exit 0
2. for a in $list ;do : ;done
часто for удобнее чем while но только в случае когда $list (обычно вывод комманды) не содержит пробелов, или, если нам на это плевать.
тут есть свои приколы, но чет я устал и не могу найти пример, кроме vzctl exec для этого случая.
while;do : ;done
обычно я использую цикл while в случае когда требуется обработка строк разделенных пробелами (в отличии от for, см. ниже)
но это не единственное различие for и while в bash. приведу простой пример
1 2 3 4 5 6 7 |
echo -e 'test test\ntest2\ntest3 test3'| while read a ;do echo ==$a exit done echo "the script finished $a" |
Здесь я хотел бы обратить внимание на то, как распределятся процессы при выполнении кода, ветки основного процесса я помечу курсивом, а ветки потомка выделю жирным
echo -e 'test test\ntest2\ntest3 test3'|
while read a ;do
echo ==$a
exit
done
echo "the script finished $a"
таким образом становится понятно, что цикл выйдет напечатав
test test
, но переменная $a останется необновленной, к тому же exit в конце выйдет всего-лишь из цикла. поэтому последняя строка вывода будет
the script finished
попробуем написать скрипт основаный на while, который напечатает все строки а в конце получит в управление переменную заданную в теле цикла., так-же выведет было ли выполнение цикла вообще.
все гораздо проще чем кажется мы просто перенесем echo в дочерний процесс избавившись от перенаправления через pipe:
while read a ;do
echo ==$a
flag=1
done < <(echo -e 'test test\ntest2\ntest3 test3')
if [ $flag ] ;then echo "the script finished, loop completed $a" else
echo "the script finished, loop didn't started";
fi
exit 0
2. for a in $list ;do : ;done
часто for удобнее чем while но только в случае когда $list (обычно вывод комманды) не содержит пробелов, или, если нам на это плевать.
тут есть свои приколы, но чет я устал и не могу найти пример, кроме vzctl exec для этого случая.