如何在 Windows 上使用 Perl 从 STDIN 读取单个字符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2021482/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I read a single character from STDIN using Perl on Windows?
提问by Mike Willekes
Using Perl, how do I capture a single character from STDIN
without needing the user to hit enter (similar to C's getch()
function)?
使用 Perl,如何在STDIN
不需要用户按 Enter 键的情况下捕获单个字符(类似于 C 的getch()
功能)?
Perl has a getc()
function, but according to the perlfunc:
Perl 有一个getc()
函数,但根据perlfunc:
However, it cannot be used by itself to fetch single characters without waiting for the user to hit enter.
但是,它本身不能用于在不等待用户按 Enter 的情况下获取单个字符。
The perlfunc docs doprovides a way to read a single character using getc()
but it requires manipulating the terminal settings using stty
. The script I'm writing needs to work on Windows (without cygwin, msys, etc.) - so that's not an option.
perlfunc 文档确实提供了一种使用读取单个字符的方法,getc()
但它需要使用stty
. 我正在编写的脚本需要在 Windows 上运行(没有 cygwin、msys 等)——所以这不是一个选项。
回答by brian d foy
From perlfaq5's answer to How can I read a single character from a file? From the keyboard?
从perlfaq5对如何从文件中读取单个字符的回答?从键盘?
You can use the builtin getc() function for most filehandles, but it won't (easily) work on a terminal device. For STDIN, either use the Term::ReadKeymodule from CPAN or use the sample code in getc in perlfunc.
您可以对大多数文件句柄使用内置的 getc() 函数,但它不会(很容易)在终端设备上工作。对于 STDIN,要么使用CPAN 中的Term::ReadKey模块,要么使用perlfunc 中 getc 中的示例代码。
If your system supports the portable operating system programming interface (POSIX), you can use the following code, which you'll note turns off echo processing as well.
如果您的系统支持可移植操作系统编程接口 (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() }
The Term::ReadKey module from CPAN may be easier to use. Recent versions include also support for non-portable systems as well.
CPAN 的 Term::ReadKey 模块可能更容易使用。最近的版本还包括对非便携式系统的支持。
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;
回答by Jonathan Feinberg
You want this module: Term::ReadKey.
你想要这个模块:Term::ReadKey。