如何在不等待进入Perl的情况下获得用户输入?

时间:2010-04-21 17:28:58

标签: perl user-input

我正在尝试在Perl中创建一个交互式shell脚本。

我能找到的唯一用户输入如下:

 $name = <STDIN>;
 print STDOUT "Hello $name\n";

但在此,用户必须始终按Enter键才能使更改生效。 如何在按下按钮后立即启动程序?

2 个答案:

答案 0 :(得分:16)

perlfaq8回答How do I read just one key without waiting for a return key?


控制输入缓冲是一个非常依赖系统的问题。在许多系统上,您可以使用stty命令,如percunc中的getc所示,但正如您所见,这已经让您陷入可移植性障碍。

open(TTY, "+</dev/tty") or die "no tty: $!";
system "stty  cbreak </dev/tty >/dev/tty 2>&1";
$key = getc(TTY);       # perhaps this works
# OR ELSE
sysread(TTY, $key, 1);  # probably this does
system "stty -cbreak </dev/tty >/dev/tty 2>&1";

CPAN的Term :: ReadKey模块提供了一个易于使用的界面,该界面应该比为每个密钥发出stty更高效。它甚至包括对Windows的有限支持。

use Term::ReadKey;
ReadMode('cbreak');
$key = ReadKey(0);
ReadMode('normal');

但是,使用代码要求您具有可用的C编译器,并且可以使用它来构建和安装CPAN模块。这是使用标准POSIX模块的解决方案,该模块已经在您的系统上(假设您的系统支持POSIX)。

use HotKey;
$key = readkey();

这是HotKey模块,隐藏了操纵POSIX termios结构的有些神秘的调用。

# HotKey.pm
package HotKey;

@ISA = qw(Exporter);
@EXPORT = qw(cbreak cooked readkey);

use strict;
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);  # ok, so i don't want echo either
    $term->setcc(VTIME, 1);
    $term->setattr($fd_stdin, TCSANOW);
}

sub cooked {
    $term->setlflag($oterm);
    $term->setcc(VTIME, 0);
    $term->setattr($fd_stdin, TCSANOW);
}

sub readkey {
    my $key = '';
    cbreak();
    sysread(STDIN, $key, 1);
    cooked();
    return $key;
}

END { cooked() }

1;

答案 1 :(得分:5)

您可以使用Term::ReadKey模块检查按键。