Дан фрагмент Bash-скрипта: cat file | while read line; do arr+=("$line"); done; echo "${#arr[@]}". Объясните, почему счётчик элементов может быть нулевым после цикла в некоторых средах, и как правильно переписать скрипт, чтобы избежать этой проблемы

11 Дек в 08:01
5 +2
0
Ответы
1
Коротко — потому что в многих оболочках команда справа от пайпа выполняется в подсhell`e`, и изменения массива там теряются при возврате в родительский шелл. В результате после `cat file | while read line; do arr+=("$line"); done` в основном процессе массива может не быть и счётчик будет равен 000.
Правильные варианты исправления (коротко, портативно и безопасно):
1) Перенаправление ввода в цикл (рекомендуемо):
```
while IFS= read -r line; do
arr+=("$line")
done < file
echo "${#arr[@]}"
```
Пояснения: `IFS=` сохраняет пробелы/табуляции, `-r` отключает интерпретацию обратных слешей. Цикл выполняется в том же процессе, массив сохраняется.
2) Использовать readarray/mapfile (bash):
```
mapfile -t arr < file
echo "${#arr[@]}"
```
Быстро и удобно; `-t` убирает завершающий символ новой строки.
3) (Менее портативно) включить в bash опцию lastpipe в неинтерактивной сессии:
```
shopt -s lastpipe
cat file | while IFS= read -r line; do arr+=("$line"); done
echo "${#arr[@]}"
```
Работает только в bash (4.2+) и при выключенном управлении заданиями.
Вывод: используйте перенаправление (`done < file`) или `mapfile` — тогда счётчик элементов не будет равен 000.
11 Дек в 08:11
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир