2010-03-19 6 views
18

Я пытаюсь создать что-то в Perl, что в основном напоминает команду Unix tee. Я пытаюсь прочитать каждую строку из STDIN, выполнить подстановку на ней и распечатать ее. (И, в конце концов, также распечатайте его в файле.) Это работает, если я использую консольный ввод, но если я попытаюсь передать вход в команду, он ничего не сделает. Вот простой пример:Как я могу прочитать входящий поток в Perl в Windows?

print "about to loop\n"; 
while(<STDIN>) 
{ 
    s/2010/2009/; 
    print; 
} 
print "done!\n"; 

Старается трубы команды режа к ней, как это:

 
C:\perltest>dir | mytee.pl 
about to loop 
done! 

Почему он не видит водопроводный вход? (Я использую Perl 5.10.0 на WinXP, если это уместно.)

+4

Кажется OS конкретным, он прекрасно работает на моем OS X поле. – zoul

+1

Это * почти * дубликат http://stackoverflow.com/questions/1286873/perl-on-windows-file-associations-and-i-o-ireirection. –

ответ

25

Это на самом деле ошибка в том, как Windows обрабатывает перенаправление ввода-вывода. Я ищу ссылку прямо сейчас, но это то, что ошибка, которая требует, чтобы указать

dir | perl filter.pl 

вместо того, чтобы иметь возможность использовать

dir | filter 

См Microsoft KB статьи STDIN/STDOUT Redirection May Not Work If Started from a File Association:

  1. Запустите редактор реестра.
  2. Найдите и выберите следующий раздел реестра: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
  3. В меню Правка выберите команду Добавить значение, а затем добавьте следующий параметр реестра:
    • Название Значение Тип InheritConsoleHandles
    • данных : REG_DWORD
    • Radix: Decimal
    • Значение: 1
  4. Закройте редактор реестра.
C:\Temp> cat filter.pl 
#!/usr/bin/perl 

while (<>) { 
    print "piped: $_"; 
}
C:\Temp> dir | filter 
piped: Volume in drive C is MAIN 
piped: Volume Serial Number is XXXX-XXXX 
piped: 
piped: Directory of C:\Temp> 
piped: 
piped: 2010/03/19 03:48 PM    . 
piped: 2010/03/19 03:48 PM    .. 
piped: 2010/03/19 03:33 PM    32 m.pm 
piped: 2010/03/19 03:48 PM    62 filter.pl
+1

спасибо синян, очень полезный ответ. это делает так, что мне не нужно обходное решение icky batch file – Jenni

+2

@Jenni Недостатком, конечно же, является то, что вы не можете быть уверены, что 'InheritConsoleHandles' будет установлен на любых других компьютерах, на которые вы могли бы развернуть свои скрипты (которые где находится 'pl2bat.bat'). Спасибо, что приняли мой ответ. –

+0

Я обнаружил, что эта ошибка в окнах не может быть надежно перекрашена. В первый раз я должен использовать * dir | perl filter.pl *. Но во второй раз он работает только с * dir | filter.pl *. Насти. – smwikipedia

12

Try:

C:\perltest>dir | perl mytee.pl 
+1

+1 Хороший улов. –

+0

Хм ... это работает, но почему я должен так его указывать? – Jenni

+3

Потому что вы на окнах. В unix вы можете поставить #!/Usr/bin/perl в верхней части файла perl, чтобы сообщить, что оболочка находится в perl. В Windows могут выполняться только файлы .exe и .com. –

0

Ну ИМХО, Perl является плохой заменой sed;)

dir | sed s/2009/2010/

+1

Я упростил часть моего сценария, которая не имеет отношения к моему вопросу. – Jenni

+12

Но perl - хорошая замена: '' sed 'не распознается как внутренняя или внешняя команда, оперативная программа или пакетный файл' ;-) – mob

1

Нет ничего плохого в попытке учиться, но быстрый поиск CPAN показывает ряд возможных решений для проблемы tee в Perl.

Например: PerlIO::Tee.

6

Может быть Microsoft KB #321788?

Сценарии, которые содержат стандартный ввод (STDIN) и стандартный вывод (STDOUT) могут не работать правильно, если вы начнете программы из командной строки и вы используете ассоциацию файлов для запуска сценария.

+0

звучит так, что это проблема. я нашел обходное решение, связанное с использованием трубопровода через файл bat, а затем вызвал исполняемый файл perl (см. принятый ответ). благодаря! – Jenni

+0

+1 @zoul Я был так занят поиском информации, я не заметил, что вы уже разместили ссылку. –

Смежные вопросы