How can I read a single character from STDIN using Perl on Windows?

Using Perl, how can I capture a single character from STDIN without requiring the user to press the enter button (similar to the C function getch() )?

Perl has a getc() function, but according to perlfunc :

However, it cannot be used on its own to extract single characters without waiting for the user to press enter.

Perlfunc docs provide a way to read a single character using getc() , but stty used to control terminal settings. The script I am writing should work on Windows (without cygwin, msys, etc.) - so this is not an option.

+5
windows perl
source share
2 answers

You need this module: Term :: ReadKey .

+9
source share

From perlfaq5 answer to How can I read one character from a file? From the keyboard?


You can use the built-in getc () function for most file descriptors, but it will not (easily) work on a terminal device. For STDIN, either use the Term :: ReadKey module from CPAN, or use the sample code in getc in perlfunc.

If your system supports the portable operating system programming interface (POSIX), you can use the following code, which you will notice, also disables echo processing.

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

The Term :: ReadKey module from CPAN may be easier to use. Recent versions also include support for non-portable systems.

 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; 
+12
source share

All Articles