Сегодня поговорим про подводные грабли.

Работая над скриптом, решил немного оптимизировать код. А чего, зачем цикл, если строка всего одна.

echo "1" |
  while read; do
    echo $REPLY,2
  done

# на

echo "1" | read
echo $REPLY,2

А не тут-то было.

1,2
,2

Во втором случае read не читает значение. Точнее, читает, иначе бы скрипт ожидал ввода с клавиатуры, но переменная REPLY пустая.

Перечитал help по read. Ничего не пойму. Пришлось обратиться к Роману.

Он пояснил, что во втором случае команда read запускается в отдельном subshell, считывает значение. Вот только передать переменную можно только в дочерние процессы, а в родительские нельзя.

Поэтому при завершении процесса read значение переменной REPLY теряется.

Пришлось читать, как работают конвейеры. Здесь писать не буду. Просто приведу ссылку на Wikipedia.

Оптимизировать можно, но так:

echo "1" | (read; echo $REPLY,2)
# или так
read < <(echo "1")
echo $REPLY,2
# если переменная одна, то классика
a=$(echo 1)
Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Всё, теперь я знаю, как работает pipeline. Надеюсь, и вы.