Perl 从标准输入输入一个字符
Perl do input one char from stdin
Perl 如何从 stdin
输入一个字符,例如
readline -N1
是吗?
您可以使用基本的 perl 发行版来做到这一点,无需安装额外的软件包:
use strict;
sub IO::Handle::icanon {
my ($fh, $on) = @_;
use POSIX;
my $ts = new POSIX::Termios;
$ts->getattr(fileno $fh) or die "tcgetattr: $!";
my $f = $ts->getlflag;
$ts->setlflag($on ? $f | ICANON : $f & ~ICANON);
$ts->setattr(fileno $fh) or die "tcsetattr: $!";
}
# usage example
# a key like `Left` or `á` may generate multiple bytes
STDIN->icanon(0);
sysread STDIN, my $c, 256;
STDIN->icanon(1);
# the read key is in $c
只读取一个字节可能不是一个好主意,因为它只会留下垃圾,以便稍后在按 Left
或 F1
等键时读取。但是,如果您想要的话,您可以将 256
替换为 1
,无论如何。
<STDIN>
会读stdin一个byte(Cchar
类型,跟一个character[=98不一样=] 如果记录分隔符设置为对数字 1 的引用,这些天通常由几个字节组成,除了 US-ASCII 字符集中的那些)。
$ echo perl | perl -le '$/ = ; $a = <STDIN>; print "<$a>"'
<p>
请注意,在下面,它可能会从输入中读取(消耗)多个字节。上面,perl
中的下一个 <STDIN>
将是 return <e>
,但可能来自事先读取的某个大缓冲区。
$ echo perl | (perl -le '$/ = ; $a = <STDIN>; print "<$a>"'; wc -c)
<p>
0
在上面,您会注意到 wc
没有收到任何输入,因为它已经被 perl
使用了。
$ echo perl | (PERLIO=raw perl -le '$/ = ; $a = <STDIN>; print "<$a>"'; wc -c)
<p>
4
这一次,wc
得到了 4 个字节(e
、r
、l
、\n
),正如我们告诉 perl
使用原始 I/O 所以 <STDIN>
转换为 read(0, bud, 1)
.
您可以使用 perl
的 read
而不是 <STDIN>
,但注意相同:
$ echo perl | (perl -le 'read STDIN, $a, 1; print "<$a>"'; wc -c)
<p>
0
$ echo perl | (PERLIO=raw perl -le 'read STDIN, $a, 1; print "<$a>"'; wc -c)
<p>
4
或者使用 sysread
这是原始 read()
:
的真正包装器
$ echo perl | (perl -le 'sysread STDIN, $a, 1; print "<$a>"'; wc -c)
<p>
4
要一次读取一个字符,您需要一次读取一个字节,直到字符结束。
您可以在 perl
中使用 <STDIN>
或 read
(不是 sysread
)对 UTF-8 编码输入(在使用该编码的语言环境中)执行此操作-C
选项,包括 raw
PERLIO
:
$ echo été | (PERLIO=raw perl -C -le '$/ = ; $a = <STDIN>; print "<$a>"'; wc -c)
<é>
4
$ echo été | (PERLIO=raw perl -C -le 'read STDIN, $a, 1; print "<$a>"'; wc -c)
<é>
4
使用 strace
,您会看到 perl
在下面执行两个 read(0, buf, 1)
系统调用来读取那个 2 字节的 é
字符。
与 ksh93 / bash 的 read -N
(或 zsh 的 read -k
)一样,如果输入未正确编码为 UTF-8,您可能会大吃一惊:
$ printf '5 12345678' | (PERLIO=raw perl -C -le 'read STDIN, $a, 1; print "<$a>"'; wc -c)
<� 1234>
4
5
(\xFD
) 通常是 UTF-8 中 6 字节字符编码的第一个字节,因此 perl
在这里读取所有 6 个字节,即使第二到第六不可能是该字符的一部分,因为它们没有设置第 8th 位。
注意,当 stdin 是 tty 设备时,read()
不会 return 直到另一端的终端发送 LF(eol
),CR(默认情况下转换为 LF),或 eof
(通常为 ^D
)或 eol2
(通常未定义)字符,如在 tty 线路规程中配置的(与 stty
命令一样)为tty 驱动程序实现了它自己的内部行编辑器,允许您在按回车键之前编辑您键入的内容。
如果您想读取为用户按下的每个键发送的字节,您需要禁用该行编辑器(bash/ksh93 的 read -N
或 zsh
的 read -k
在 stdin 是 tty 时执行),请参阅 @guest's answer 了解如何执行此操作的详细信息。
¹ 虽然现在 Unicode 将代码点限制为最多 0x10FFFF,这意味着 UTF-8 编码最多有 4 个字节,但 UTF-8 最初设计用于编码最多 0x7fffffff(最多 6 个字节)的代码点编码)和 perl
将其扩展到最多 0x7FFFFFFFFFFFFFFFF(13 字节编码)
Perl 如何从 stdin
输入一个字符,例如
readline -N1
是吗?
您可以使用基本的 perl 发行版来做到这一点,无需安装额外的软件包:
use strict;
sub IO::Handle::icanon {
my ($fh, $on) = @_;
use POSIX;
my $ts = new POSIX::Termios;
$ts->getattr(fileno $fh) or die "tcgetattr: $!";
my $f = $ts->getlflag;
$ts->setlflag($on ? $f | ICANON : $f & ~ICANON);
$ts->setattr(fileno $fh) or die "tcsetattr: $!";
}
# usage example
# a key like `Left` or `á` may generate multiple bytes
STDIN->icanon(0);
sysread STDIN, my $c, 256;
STDIN->icanon(1);
# the read key is in $c
只读取一个字节可能不是一个好主意,因为它只会留下垃圾,以便稍后在按 Left
或 F1
等键时读取。但是,如果您想要的话,您可以将 256
替换为 1
,无论如何。
请注意,在下面,它可能会从输入中读取(消耗)多个字节。上面, 在上面,您会注意到 这一次, 您可以使用 或者使用 要一次读取一个字符,您需要一次读取一个字节,直到字符结束。 您可以在 使用 与 ksh93 / bash 的 注意,当 stdin 是 tty 设备时, 如果您想读取为用户按下的每个键发送的字节,您需要禁用该行编辑器(bash/ksh93 的 ¹ 虽然现在 Unicode 将代码点限制为最多 0x10FFFF,这意味着 UTF-8 编码最多有 4 个字节,但 UTF-8 最初设计用于编码最多 0x7fffffff(最多 6 个字节)的代码点编码)和 <STDIN>
会读stdin一个byte(Cchar
类型,跟一个character[=98不一样=] 如果记录分隔符设置为对数字 1 的引用,这些天通常由几个字节组成,除了 US-ASCII 字符集中的那些)。
$ echo perl | perl -le '$/ = ; $a = <STDIN>; print "<$a>"'
<p>
perl
中的下一个 <STDIN>
将是 return <e>
,但可能来自事先读取的某个大缓冲区。$ echo perl | (perl -le '$/ = ; $a = <STDIN>; print "<$a>"'; wc -c)
<p>
0
wc
没有收到任何输入,因为它已经被 perl
使用了。$ echo perl | (PERLIO=raw perl -le '$/ = ; $a = <STDIN>; print "<$a>"'; wc -c)
<p>
4
wc
得到了 4 个字节(e
、r
、l
、\n
),正如我们告诉 perl
使用原始 I/O 所以 <STDIN>
转换为 read(0, bud, 1)
.perl
的 read
而不是 <STDIN>
,但注意相同:$ echo perl | (perl -le 'read STDIN, $a, 1; print "<$a>"'; wc -c)
<p>
0
$ echo perl | (PERLIO=raw perl -le 'read STDIN, $a, 1; print "<$a>"'; wc -c)
<p>
4
sysread
这是原始 read()
:$ echo perl | (perl -le 'sysread STDIN, $a, 1; print "<$a>"'; wc -c)
<p>
4
perl
中使用 <STDIN>
或 read
(不是 sysread
)对 UTF-8 编码输入(在使用该编码的语言环境中)执行此操作-C
选项,包括 raw
PERLIO
:$ echo été | (PERLIO=raw perl -C -le '$/ = ; $a = <STDIN>; print "<$a>"'; wc -c)
<é>
4
$ echo été | (PERLIO=raw perl -C -le 'read STDIN, $a, 1; print "<$a>"'; wc -c)
<é>
4
strace
,您会看到 perl
在下面执行两个 read(0, buf, 1)
系统调用来读取那个 2 字节的 é
字符。read -N
(或 zsh 的 read -k
)一样,如果输入未正确编码为 UTF-8,您可能会大吃一惊:$ printf '5 12345678' | (PERLIO=raw perl -C -le 'read STDIN, $a, 1; print "<$a>"'; wc -c)
<� 1234>
4
5
(\xFD
) 通常是 UTF-8 中 6 字节字符编码的第一个字节,因此 perl
在这里读取所有 6 个字节,即使第二到第六不可能是该字符的一部分,因为它们没有设置第 8th 位。read()
不会 return 直到另一端的终端发送 LF(eol
),CR(默认情况下转换为 LF),或 eof
(通常为 ^D
)或 eol2
(通常未定义)字符,如在 tty 线路规程中配置的(与 stty
命令一样)为tty 驱动程序实现了它自己的内部行编辑器,允许您在按回车键之前编辑您键入的内容。read -N
或 zsh
的 read -k
在 stdin 是 tty 时执行),请参阅 @guest's answer 了解如何执行此操作的详细信息。
perl
将其扩展到最多 0x7FFFFFFFFFFFFFFFF(13 字节编码)