Вместо использования \n
вы можете добавить обратную косую черту \
, нажать Enter и продолжить на следующей строке с помощью команды:
sed -i.bak 's/|/\
/g' inp.txt
Чтобы заменить оставшийся пробел и |
в конце строки ($
), используйте
sed -i.bak 's/ |$/\
/' inp.txt
Для одной замены флаг g
не нужен.
По крайней мере, в Linux вы можете определить, был ли закрыт другой конец канала, используя poll()
с POLLHUP
в маске событий.
Но учтите, что в этот момент в конвейере могут быть данные, готовые к чтению, так что вы, вероятно, захотите проверить и это. Опять же, в Linux это можно сделать с помощью FIONREAD
ioctl.
Таким образом, вы можете определить:
stdin_alive() {
perl -MIO::Poll -e '
require "sys/ioctl.ph";
-p STDIN or die "stdin is not a pipe\n";
$p = IO::Poll->new;
$p->mask(STDIN, POLLHUP);
if ($p->poll(0)) {
ioctl(STDIN, &FIONREAD, $n) or die "FIONREAD: $!\n";
$n = unpack "L", $n;
exit 1 unless $n;
}'
}
И использовать как:
step1 | while stdin_alive; do step2; done
Другой подход — использовать команду ifne
изmoreutils
:
step1 |
while
ifne sh -c 'step2 && exit 42'
[ "$?" -eq 42 ]
do
continue
done
ifne
пытается прочитать его стандартный ввод. Если хотя бы один байт был прочитан, то ifne
запускает команду со своим стандартным вводом, подключенным к новому каналу, и перебирает то, что она читает, из своего стандартного ввода через этот новый канал в команду, поэтому он менее эффективен в том смысле, что есть дополнительное перелопачивание. и транзит через дополнительную трубу, но это означает, что он может работать независимо от типа ввода (не только трубы ).
Еще одно отличие от предыдущего решения заключается в том, что ifne
ожидает ввода на стандартный ввод перед запуском step2
,в то время как подход poll()
+ FIONREAD
просто проверяет, работает ли канал в точный момент времени проверки, есть ли в канале данные или нет. Однако это можно изменить, добавив POLLIN
в список опрашиваемых событий.