Как мне прочитать один символ из STDIN, используя Perl в Windows? - PullRequest
6 голосов
/ 07 января 2010

Используя Perl, как мне захватить один символ из STDIN без необходимости нажимать клавишу ввода (аналогично функции C getch())?

Perl имеет функцию getc(), но в соответствии с perlfunc :

Тем не менее, он не может быть использован для извлечения одиночные персонажи, не дожидаясь пользователь должен нажать Enter.

Perlfunc docs do предоставляет способ прочитать один символ, используя getc(), но требует манипулирования настройками терминала, используя stty. Скрипт, который я пишу, должен работать в Windows (без cygwin, msys и т. Д.), Так что это не вариант.

Ответы [ 2 ]

13 голосов
/ 07 января 2010

От ответа perlfaq5 на Как я могу прочитать один символ из файла? С клавиатуры?


Вы можете использовать встроенную функцию getc () для большинства файловых дескрипторов, но она не будет (легко) работать на терминальном устройстве. Для STDIN либо используйте модуль Term :: ReadKey из CPAN, либо используйте пример кода в getc в perlfunc.

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

#!/usr/bin/perl -w
use strict;
$| = 1;
for (1..4) {
    my $got;
    print "gimme: ";
    $got = getone();
    print "--> $got\n";
    }
exit;

BEGIN {
use POSIX qw(:termios_h);

my ($term, $oterm, $echo, $noecho, $fd_stdin);

$fd_stdin = fileno(STDIN);

$term     = POSIX::Termios->new();
$term->getattr($fd_stdin);
$oterm     = $term->getlflag();

$echo     = ECHO | ECHOK | ICANON;
$noecho   = $oterm & ~$echo;

sub cbreak {
    $term->setlflag($noecho);
    $term->setcc(VTIME, 1);
    $term->setattr($fd_stdin, TCSANOW);
    }

sub cooked {
    $term->setlflag($oterm);
    $term->setcc(VTIME, 0);
    $term->setattr($fd_stdin, TCSANOW);
    }

sub getone {
    my $key = '';
    cbreak();
    sysread(STDIN, $key, 1);
    cooked();
    return $key;
    }

}

END { cooked() }

Модуль Term :: ReadKey из CPAN может быть проще в использовании. Последние версии также включают поддержку непереносимых систем.

use Term::ReadKey;
open(TTY, "</dev/tty");
print "Gimme a char: ";
ReadMode "raw";
$key = ReadKey 0, *TTY;
ReadMode "normal";
printf "\nYou said %s, char number %03d\n",
    $key, ord $key;
10 голосов
/ 07 января 2010

Вы хотите этот модуль: Term :: ReadKey .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...