如何在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:42:31  来源:igfitidea点击:

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

windowsperl

提问by Mike Willekes

Using Perl, how do I capture a single character from STDINwithout 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