Как сделать две команды потреблять входные данные из stdin последовательно?

Следующий скрипт perl consume-10-lines-and-exit читает десять строк из stdin и печатает их. После этого он выходит.

 #!/usr/bin/env perl use strict; use warnings FATAL => 'all'; for (my $i = 0; $i < 10; $i++) { my $line = <STDIN>; print $line; } 

Я пытаюсь скомбинировать consume-10-lines-and-exit и cat таким образом, что первые десять строк ввода и потребляются и печатаются первой командой, а затем остальные потребляются cat .

В следующем коде несколько фрагментов печатаются от 1 до 10 вместо 1 до 13, как я ожидал.

 printf '1 2 3 4 5 6 7 8 9 10 11 12 13' \ | tr ' ' '\n' | { perl consume-10-lines-and-exit; cat; } printf '1 2 3 4 5 6 7 8 9 10 11 12 13' \ | tr ' ' '\n' | ( perl consume-10-lines-and-exit; cat ) printf '1 2 3 4 5 6 7 8 9 10 11 12 13' \ | tr ' ' '\n' | sh -c 'perl consume-10-lines-and-exit; cat' 

Есть ли конструкция для команд секвенирования, чтобы они считывали входные данные из stdin до тех пор, пока они не выйдут, а затем следующая команда будет продолжена там, где предыдущий остановился?

3 Solutions collect form web for “Как сделать две команды потреблять входные данные из stdin последовательно?”

Ваша проблема в том, что perl использует буферизованный вход, поэтому читает вперед за пределами линий, которые вы хотите использовать. Попробуйте эту байтовую версию:

 perl -e ' use strict; use warnings FATAL => "all"; for (my $i = 0; $i < 10; $i++) { my $line; while(sysread(*STDIN,my $char,1)==1){ $line .= $char; last if $char eq "\n"; } print $line; }' 

Использование команд группировки подходит для выполнения этого задания, но виновником является ввод, который вы вводите командам группировки, которые не доступны для поиска.

POSIX определяет в разделе INPUT FILE что:

Когда стандартная утилита считывает запрашиваемый входной файл и завершается без ошибки до того, как он достигнет конца файла, утилита должна убедиться, что смещение файла в описании открытого файла должным образом расположено непосредственно за последним байтом, обработанным этой утилитой. Для файлов, которые не доступны для поиска, состояние смещения файла в описании открытого файла для этого файла неуказано

perl – не стандартная утилита, но есть большая вероятность, что она соответствует стандартной спецификации. Если вы сделаете файл доступным для поиска, тогда он будет работать:

 $ seq 13 > /tmp/test $ {perl -e 'for($i=0;$i<10;$i++){$line = <STDIN>;print $line}'; cat;} </tmp/test 1 2 3 4 5 6 7 8 9 10 11 12 13 

Если вы не хотите использовать файл с возможностью поиска, вы можете заставить perl использовать более низкий уровень, который вызывает функции системных вызовов read() , write() , lseek() для IO:

 $ seq 13 | { PERLIO=:unix perl -e 'for($i=0;$i<10;$i++){$line = <STDIN>;print $line}' cat } 

Буферизация также может быть отключена путем прокрутки с уровнями PerlIO (см. Также perlrun ). Кроме того, этот неудобный и подробный цикл C-стиля можно более легко записать как ... for 1..10 или for my $i (1..10) { ... } .

 $ perl -E 'say for 1..12' \ | ( PERLIO=:unix perl -e 'print "perl " . scalar <STDIN> for 1..10'; cat ) perl 1 perl 2 perl 3 perl 4 perl 5 perl 6 perl 7 perl 8 perl 9 perl 10 11 12 $ 
  • Корневая оболочка ошибочно изменилась. Как я могу изменить его на действительную оболочку?
  • Как разбить файл и вывести его из команды?
  • Эквивалент cmd "for" в bash?
  • ksh, выполнить действие при достижении максимального значения цикла
  • Увеличить ширину символов в оболочке сервера Ubuntu?
  • Внедрить собственную оболочку
  • Запустите подчиненную оболочку, затем запустите команды
  • Разница между выполнением нескольких команд с && и;
  • Чтение вывода в `screen` извне
  • Как получить функции, распространяемые на подоболочку?
  • как фильтровать по звездочке или аналогичному выражению rsync в zsh
  • Linux и Unix - лучшая ОС в мире.