這個問題是從 Unix & Linux Stack Exchange遷移過來的,因為它可以在 Stack Overflow 上回答。 4 小時前遷移 。
Perl 如何從stdin一個字符輸入
readline -N1
做?
uj5u.com熱心網友回復:
您可以使用基本的 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只要您愿意,都可以替換為。
uj5u.com熱心網友回復:
<STDIN>將讀取標準輸入一個位元組(Cchar型,這是不一樣的一個字符這些天通常由除了那些在US-ASCII字符集幾個位元組)如果記錄分離器被設定為基準在從stdin一個時間到數字 1。
$ echo perl | perl -le '$/ = \1; $a = <STDIN>; print "<$a>"'
<p>
請注意,在下面,它可能會從輸入中讀取(消耗)一個以上的位元組。上面,下一個<STDIN>insideperl將回傳<e>,但可能來自一些預先讀取的大緩沖區。
$ echo perl | (perl -le '$/ = \1; $a = <STDIN>; print "<$a>"'; wc -c)
<p>
0
在上面,您會注意到wc沒有收到任何輸入,因為它已經被perl.
$ echo perl | (PERLIO=raw perl -le '$/ = \1; $a = <STDIN>; print "<$a>"'; wc -c)
<p>
4
這一次,wc得到了 4 個位元組(e, r, l, \n),因為我們告訴perl使用原始 I/O,因此<STDIN>轉換為read(0, bud, 1).
代替<STDIN>,您可以使用perl'sread并具有相同的警告:
$ 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哪個是 raw 的真正包裝器read():
$ echo perl | (perl -le 'sysread STDIN, $a, 1; print "<$a>"'; wc -c)
<p>
4
要一次讀取一個字符,您需要一次讀取一個位元組,直到字符結束。
您可以使用perlwith<STDIN>或read(not sysread)-C選項對 UTF-8 編碼輸入(在使用該編碼的語言環境中)執行此操作,包括使用raw PERLIO:
$ echo été | (PERLIO=raw perl -C -le '$/ = \1; $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 '\375 12345678' | (PERLIO=raw perl -C -le 'read STDIN, $a, 1; print "<$a>"'; wc -c)
<? 1234>
4
\375( \xFD) 通常是 UTF-81 中 6 位元組字符編碼的第一個位元組,因此perl在此處讀取所有 6 個位元組,即使第二到第六個位元組不可能是該字符的一部分,因為它們沒有 8第 1位設定。
請注意,當 stdin 是 tty 設備時,read()將不會回傳,直到另一端的終端發送 LF ( eol)、CR(默認轉換為 LF)或eof(通常^D)或eol2(通常未定義)字符,如配置tty 行規則(與stty命令一樣),因為 tty 驅動程式實作了它自己的內部行編輯器,允許您在按 Enter 之前編輯您鍵入的內容。
如果您想讀取為用戶在那里按下的每個鍵發送的位元組,您需要禁用該行編輯器(當 stdin 是 tty 時,bash/ksh93read -N或zsh'sread -k會這樣做),有關如何執行此操作的詳細資訊,請參閱@guest 的回答。
1 雖然現在 Unicode 將代碼點限制為最多 0x10FFFF,這意味著 UTF-8 編碼最多有 4 個位元組,但 UTF-8 最初設計用于編碼最多 0x7fffffff(最多 6 個位元組編碼)的代碼點,并將其perl擴展到最多 0x7FFFFFFFFFFFFFF( 13 位元組編碼)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/382517.html
