Могу ли я запросить ввод данных пользователем после прочтения ввода по каналу STDIN в Perl? - PullRequest
12 голосов
/ 28 февраля 2012

Я пытаюсь написать Perl-скрипт, который читает данные по каналам, а затем запрашивает ввод данных на основе этих данных. Следующий скрипт, prompt_for_action, это то, что я пытаюсь сделать:

#!/usr/bin/perl 

my @hosts = ();
while (<>) {
    my $host = $_;
    $host =~ s/\n//; # strip newlines
    push(@hosts, $host);
}

for my $host (@hosts) {
    print "Do you want to do x with $host ? y/n: ";
    chomp(my $answer = <>);
    print "You said `$answer`.\n";
}

но когда я запускаю его, пользователь не ждет ввода, он просто проходит, не дожидаясь, пока я наберу:

$ echo "test1.example.com
> test2.example.com" | ./prompt_for_action
Do you want to do x with test1.example.com ? y/n: You said ``.
Do you want to do x with test2.example.com ? y/n: You said ``.

Если я не читаю свои данные из STDIN ...

#!/usr/bin/perl 

my @hosts = ('test1.example.com', 'test12.example.com');

for my $host (@hosts) {
    print "Do you want to do x with $host ? y/n: ";
    chomp(my $answer = <>);
    print "You said `$answer`.\n";
}

тогда скрипт работает нормально:

$ ./prompt_for_action 
Do you want to do x with test1.example.com ? y/n: y
You said `y`.
Do you want to do x with test12.example.com ? y/n: n
You said `n`.

Возможно ли передать по трубопроводу в STDIN, а затем запросить ввод пользователя? Если так, то как?

Ответы [ 3 ]

12 голосов
/ 28 февраля 2012

В системах Unix-y вы можете открыть псевдофайл /dev/tty для чтения.

while (<STDIN>) {
    print "from STDIN: $_";
}
close STDIN;

# oops, need to read something from the console now
open TTY, '<', '/dev/tty';
print "Enter your age: ";
chomp($age = <TTY>);
close TTY;
print "You look good for $age years old.\n";
0 голосов
/ 27 октября 2018

Что касается не-Unix-y систем, вы можете использовать findConsole из Term :: ReadLine , а затем использовать его вывод, как в ответ моба , например вместо /dev/tty вставьте в вывод findConsole первый элемент.

Пример в Windows:

use Term::ReadLine;
while (<STDIN>) {
    print "from STDIN: $_";
}
close STDIN;

# oops, need to read something from the console now
my $term = Term::ReadLine->new('term');
my @_IO = $term->findConsole();
my $_IN = $_IO[0];
print "INPUT is: $_IN\n";
open TTY, '<', $_IN;
print "Enter your age: ";
chomp($age = <TTY>);
close TTY;
print "You look good for $age years old.\n";

выходы:

echo SOME | perl tty.pl
from STDIN: SOME
INPUT is: CONIN$
Enter your age: 12 # you can now enter here!
You look good for 12 years old.
0 голосов
/ 28 февраля 2012

Как только вы передадите что-то через STDIN, ваш прежний STDIN (ввод с клавиатуры) будет заменен каналом.Поэтому я не думаю, что это возможно.

...