У меня проблема в одном из моих скриптов оболочки. Спросил несколько коллег, но они все только качают головами (после некоторого расчесывания), поэтому я пришел сюда за ответом.
Согласно моему пониманию следующий скрипт оболочки должен вывести «Count is 5» в качестве последней строки. За исключением того, что это не так. Это печатает "Количество равно 0". Если заменить «while read» на любой другой вид цикла, он работает просто отлично. Вот сценарий:
echo "1"> input.data echo "2" >> input.data echo "3" >> input.data echo "4" >> input.data echo "5" >> input.data CNT = 0 cat input.data | пока читаешь; делать пусть CNT ++; echo "Подсчет в $ CNT" сделанный echo "Count is $ CNT"
Почему это происходит и как я могу предотвратить это? Я пробовал это в Debian Lenny и Squeeze, тот же результат (то есть bash 3.2.39 и bash 4.1.5. Я полностью признаю, что не являюсь мастером сценариев оболочки, поэтому любые указатели приветствуются.
Это своего рода «распространенная» ошибка. Каналы создают SubShells, поэтому они
while read
работают в оболочке, отличной от вашего скрипта, что делает вашуCNT
переменную никогда не изменяющейся (только ту, которая находится внутри подоболочки трубы).Сгруппируйте последний
echo
с подоболочкой,while
чтобы исправить это (есть много других способов исправить это, это один. Ответы Iain и Ignacio имеют другие.)Длинное объяснение:
CNT
в своем скрипте значение 0;|
towhile read
;$CNT
переменная экспортируется в SubShell со значением 0;CNT
значение до 5;echo
ваше первоначальноеCNT
значение 0.источник
Это работает
источник
let CNT++
которая должна вместо этогоCNT="$((CNT+1))"
использовать POSIX-совместимое арифметическое расширение . Остальное уже портативно.Попробуйте вместо этого передать данные в под-оболочку, как будто это файл перед циклом while. Это похоже на решение Lain, но предполагает, что вам не нужен прерывистый файл:
источник