2010-01-07 5 views
5

En utilisant Perl, comment capturer un seul caractère de STDIN sans que l'utilisateur doive appuyer sur Entrée (similaire à la fonction getch() de C)?Comment lire un seul caractère de STDIN en utilisant Perl sous Windows?

Perl a une fonction getc(), mais selon la perlfunc:

Cependant, il ne peut pas être utilisé par lui-même pour aller chercher caractères simples sans attendre l'utilisateur appuyez sur Entrée.

Les perlfunc docs ne pas fournit un moyen de lire un caractère unique à l'aide getc() mais il nécessite de manipuler les paramètres du terminal à l'aide stty. Le script que j'écris doit fonctionner sous Windows (sans cygwin, msys, etc.) - donc ce n'est pas une option.

Répondre

9

Vous voulez ce module: Term::ReadKey.

+1

A-t-il été porté sur Windows? – gameover

+5

Avez-vous * lu * la page liée? –

+1

Merci! J'utilisais déjà Term :: Readkey pour désactiver l'écho (pour la saisie du mot de passe). Cela fonctionne très bien. –

12

De la réponse de perlfaq5 à How can I read a single character from a file? From the keyboard?


Vous pouvez utiliser la fonction builtin getc() pour la plupart des descripteurs de fichier, mais il ne sera pas (facilement) travailler sur un dispositif terminal. Pour STDIN, utilisez le module Term::ReadKey de CPAN ou utilisez l'exemple de code dans getc dans perlfunc.

Si votre système prend en charge l'interface de programmation du système d'exploitation portable (POSIX), vous pouvez utiliser le code suivant, que vous noterez également, qui désactive le traitement de l'écho.

#!/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() } 

Le module Term :: ReadKey de CPAN peut être plus facile à utiliser. Les versions récentes incluent également le support pour les systèmes non portables.

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; 
+0

@Brain: Est-ce que Term :: ReadKey est disponible via activePerl? – gameover

+2

Cela devrait vous dire si vous l'avez installé (je l'ai sur ActiveState 5.10.1): perl -MTerm :: ReadKey -e 1 – toolic

+3

@gameover: 'ppm recherche Terme :: ReadKey' indique qu'il est. – Anonymous

Questions connexes