【问题标题】:How do I read a single character from STDIN using Perl on Windows?如何在 Windows 上使用 Perl 从 STDIN 读取单个字符?
【发布时间】:2017-07-08 21:24:07
【问题描述】:

使用 Perl,我如何从 STDIN 捕获单个字符而不需要用户按 Enter(类似于 C 的 getch() 函数)?

Perl 有一个getc() 函数,但是根据perlfunc

但是不能单独使用它来获取 单个字符无需等待 用户按回车键。

perlfunc 文档 do 提供了一种使用 getc() 读取单个字符的方法,但它需要使用 stty 操作终端设置。我正在编写的脚本需要在 Windows 上运行(没有 cygwin、msys 等)——所以这不是一个选项。

【问题讨论】:

    标签: windows perl


    【解决方案1】:

    来自perlfaq5How can I read a single character from a file? From the keyboard?的回复


    您可以对大多数文件句柄使用内置的 getc() 函数,但它不会(轻松)在终端设备上工作。对于 STDIN,要么使用 CPAN 中的 Term::ReadKey 模块,要么使用 perlfunc 中 getc 中的示例代码。

    如果您的系统支持可移植操作系统编程接口 (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() }
    

    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;
    

    【讨论】:

    • @Brain: Term::ReadKey 是否可以通过 activePerl 获得?
    • @gameover: ppm search Term::ReadKey 表示它是。
    • 请记住,ActivePerl 是在多个平台上运行的 Perl 发行版。如果您担心某个特定平台,请询问该平台。 :)
    【解决方案2】:

    你想要这个模块:Term::ReadKey

    【讨论】:

    • 移植到windows了吗?
    • 谢谢!我已经在使用 Term::Readkey 禁用回显(用于密码输入)。这很好用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多