如何在 Raku 中使用 get / prompt 获取 stdin ($*IN) 后清除 EOF?

How can I clear EOF on stdin ($*IN) after gettig it with get / prompt in Raku?

提问人:cowbaymoo 提问时间:4/5/2021 更新时间:4/23/2021 访问量:279

问:

在我的程序中,我想从循环中读取一行,为此我可以使用 or ;但是,我注意到,如果我立即使用 EOF 结束我的输入(例如,在 Linux / MacOS 中使用 Ctrl-D),那么任何后续使用 or 从中读取另一行都将导致它返回,这意味着它仍然从 .$*INgetpromptgetprompt$*INNil$*IN

例:

dd get;
dd get;

使用即时 EOF (ctrl-d),程序结束并输出两个 's。Nil

如果输入的内容不是 EOF,则不会发生此问题。

奇怪的是,这个问题也不会发生在 .即,slurp

dd slurp;
dd slurp;

在第一个 ctrl-d 之后,由第一个 ctrl-d 打印,然后由于第二个 .""ddslurp

我认为这也是他们同样的问题 - https://github.com/rakudo/rakudo/issues/4196

获取 stdin 提示 eof raku

评论

0赞 jubilatious1 4/16/2021
这不是期望/首选的行为吗?否则,“传输”(阅读:恶意制作的消息)可以毫不费力地束缚机器。
1赞 Håkon Hægland 4/22/2021
添加了错误报告

答:

5赞 Håkon Hægland 4/12/2021 #1

根据这个 Perl 5 答案,您可以在收到 EOF 后通过打开以下方式重新打开 STDIN:/dev/tty

use v6;
print "Input line: ";
my $line = get;
if ($line === Any) {
    say "got EOF..";
    say "Reopening STDIN..";
    my $fh = open "/dev/tty", :r, chomp => $*IN.chomp, nl-in => $*IN.nl-in,
        encoding => $*IN.encoding;
    print "Enter new line: ";
    my $line = $fh.get();
    say "Got line: {$line}";
}
else {
    say "Not EOF, got line: {$line}";
}

以上有效,但我不确定如何将重新打开的 STDIN 句柄重新分配给 ..$*IN

我尝试了以下方法:

$*IN = IO::Handle.new(path => IO::Path.new("/dev/tty"), :r,
                        chomp => $*IN.chomp, nl-in => $*IN.nl-in,
                        encoding => $*IN.encoding);

但它没有重新开放......$*IN

编辑

我也试过:

print "Input line: ";
my $line = get;
if ($line === Any) {
    say "got EOF..";
    say "Reopening STDIN..";
    $*IN.close;
    $*IN = open "/dev/tty", :r, chomp => $*IN.chomp, nl-in => $*IN.nl-in,
        encoding => $*IN.encoding;
    my $line = get;
    say "Got line: {$line}";
}
else {
    say "Not EOF, got line: {$line}";
}

但它没有用:

Input line: got EOF..
Reopening STDIN..
Cannot do 'get' on a handle in binary mode
  in block <unit> at ./11.raku line 12

编辑 2

我想我发现了问题,在上面的脚本中,您必须使用而不是(我不确定为什么,看起来这可能是一个错误)my $line = $*IN.getmy $line = get

评论

0赞 cowbaymoo 4/12/2021
感谢您的尝试。这绝对是Rakudo的一个错误。
1赞 ugexe 4/12/2021
分配句柄不会自动为您打开它。打开手柄,或做例如$*IN$*IN = $fh
0赞 Håkon Hægland 4/13/2021
@ugexe 不幸的是,这也行不通。分配使抛掷,即使其参数显示 。这是我使用的代码的链接。$*IN = $fhget()Cannot do 'get' on a handle in binary modeencodingutf8
0赞 ugexe 4/13/2021
对我来说,在我做第二个cntrl + d之前,我一直在你的例子上工作$*IN = $fh
0赞 Håkon Hægland 4/15/2021
@ugexe “对我来说 $*IN = $fh 适用于您的示例,直到我执行第二个 cntrl+d” 奇怪,这是我得到的输出(运行脚本)。我给出的唯一输入是第一个提示时的 CTRL-D。