Поскольку я влюбляюсь в это, я хотел бы оставить записку. Я нашел этот поток, потому что мне нужно переписать старый скрипт sh, чтобы он был POSIX-совместимым. Это в основном означает обойти проблему pipe / subshell, представленную POSIX, переписав код следующим образом:
some_command | read a b c
в:
read a b c << EOF
$(some_command)
EOF
И код так:
some_command |
while read a b c; do
# something
done
в:
while read a b c; do
# something
done << EOF
$(some_command)
EOF
Но последний не ведет себя так же при пустом вводе. В старой нотации цикл while не вводится при пустом вводе, но в нотации POSIX это так! Я думаю, что это связано с символом новой строки перед EOF, который нельзя пропустить. Код POSIX, который ведет себя больше как старая нотация, выглядит следующим образом:
while read a b c; do
case $a in ("") break; esac
# something
done << EOF
$(some_command)
EOF
В большинстве случаев это должно быть достаточно хорошо. Но, к сожалению, это все еще ведет себя не совсем так, как старые записи, если some_command выводит пустую строку. В старой нотации выполняется тело while, а в нотации POSIX мы разбиваемся перед телом.
Подход, чтобы исправить это, может выглядеть так:
while read a b c; do
case $a in ("something_guaranteed_not_to_be_printed_by_some_command") break; esac
# something
done << EOF
$(some_command)
echo "something_guaranteed_not_to_be_printed_by_some_command"
EOF