27

PHP のコマンド ラインから一度に 1 文字ずつ読み取りたいのですが、どこかからの何らかの入力バッファリングがこれを妨げているようです。

次のコードを検討してください。

#!/usr/bin/php
<?php
echo "input# ";
while ($c = fread(STDIN, 1)) {
    echo "Read from STDIN: " . $c . "\ninput# ";
}
?>

入力として「foo」と入力して(Enterキーを押して)、得られる出力は次のとおりです。

input# foo
Read from STDIN: f
input# Read from STDIN: o
input# Read from STDIN: o
input# Read from STDIN: 

input# 

私が期待している出力は次のとおりです。

input# f
input# Read from STDIN: f

input# o
input# Read from STDIN: o

input# o
input# Read from STDIN: o

input# 
input# Read from STDIN: 

input# 

(つまり、入力時に文字が読み取られ、処理されます)。

ただし、現在、各文字は、Enter キーが押された後にのみ読み取られます。TTY が入力をバッファリングしている疑いがあります。

最終的には、上矢印、下矢印などのキー押下を読み取れるようにしたい.

4

4 に答える 4

35

私にとっての解決策は-icanon、TTYでモードを設定することでした(を使用stty)。例えば。:

stty -icanon

したがって、現在機能するコードは次のとおりです。

#!/usr/bin/php
<?php
system("stty -icanon");
echo "input# ";
while ($c = fread(STDIN, 1)) {
    echo "Read from STDIN: " . $c . "\ninput# ";
}
?>

出力:

input# fRead from STDIN: f
input# oRead from STDIN: o
input# oRead from STDIN: o
input# 
Read from STDIN: 

input# 

ここで与えられた答えの小道具:(
リモート)ターミナルセッションからキープレスを待って取得する方法はありますか?

詳細については、http:
//www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html#AEN92を参照してください。

作業が完了したら、TTY を復元することを忘れないでください...

tty 構成の復元

端末を変更する前に tty の状態を保存することで、端末を元の状態にリセットできます。完了したら、その状態に戻すことができます。

例えば:

<?php

// Save existing tty configuration
$term = `stty -g`;

// Make lots of drastic changes to the tty
system("stty raw opost -ocrnl onlcr -onocr -onlret icrnl -inlcr -echo isig intr undef");

// Reset the tty back to the original configuration
system("stty '" . $term . "'");

?>

これが tty を保持し、開始前のユーザーの状態に戻す唯一の方法です。

元の状態を維持することを心配していない場合は、次のようにするだけで、デフォルトの「正常な」構成にリセットできます。

<?php

// Make lots of drastic changes to the tty
system("stty raw opost -ocrnl onlcr -onocr -onlret icrnl -inlcr -echo isig intr undef");

// Reset the tty back to sane defaults
system("stty sane");

?>
于 2010-09-10T12:24:58.420 に答える
6

以下の関数は、単一の文字をキャプチャするために使用できる @seb の回答の簡略化されたバージョンです。を必要とせず、while ループを作成するのではなく、固有のブロッキングstream_selectを使用します。readline_callback_handler_installまた、ハンドラーを削除して、通常どおり追加の入力 (readline など) を許可します。

function readchar($prompt)
{
    readline_callback_handler_install($prompt, function() {});
    $char = stream_get_contents(STDIN, 1);
    readline_callback_handler_remove();
    return $char;
}

// example:
if (!in_array(
    readchar('Continue? [Y/n] '), ["\n", 'y', 'Y']
    // enter/return key ("\n") for default 'Y'
)) die("Good Bye\n");
$name = readline("Name: ");
echo "Hello {$name}.\n";
于 2016-07-05T17:10:27.533 に答える