2010-01-07 6 views
5

Usando Perl, ¿cómo puedo capturar un solo carácter de STDIN sin necesidad de que el usuario presione enter (similar a la función de C getch())?¿Cómo leo un solo carácter de STDIN usando Perl en Windows?

Perl tiene una función getc(), pero de acuerdo con la perlfunc:

Sin embargo, no se puede utilizar por sí mismo a buscar caracteres individuales sin esperar a que el usuario pulsa enter.

Los documentos perlfunc do proporciona una manera de leer un solo carácter utilizando getc() pero requiere la manipulación de los ajustes del terminal utilizando stty. El script que estoy escribiendo necesita funcionar en Windows (sin cygwin, msys, etc.), así que esa no es una opción.

Respuesta

9

Desea este módulo: Term::ReadKey.

+1

¿Ha sido portado en windows? – gameover

+5

¿Leyó * la página enlazada? –

+1

¡Gracias! Ya estaba usando Term :: Readkey para desactivar el eco (para ingresar la contraseña). Esto funciona genial –

12

De respuesta perlfaq5 's a How can I read a single character from a file? From the keyboard?


Puede utilizar la función incorporada getc() para la mayoría de controladores de archivo, pero no (fácilmente) trabajar en un dispositivo terminal. Para STDIN, use el módulo Term::ReadKey de CPAN o use el código de muestra en getc in perlfunc.

Si su sistema es compatible con la interfaz de programación del sistema operativo portátil (POSIX), puede usar el siguiente código, que también notará que desactiva el procesamiento de eco.

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

El módulo Term :: ReadKey de CPAN puede ser más fácil de usar. Las versiones recientes también incluyen soporte para sistemas no portátiles.

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: ¿Term :: ReadKey está disponible a través de activePerl? – gameover

+2

Esto debería decirle si lo tiene instalado (lo tengo en ActiveState 5.10.1): perl -MTerm :: ReadKey -e 1 – toolic

+3

@gameover: 'ppm search Term :: ReadKey' indica que sí lo está. – Anonymous

Cuestiones relacionadas