dan*_*mau 25 php stdin command-line-interface buffering tty
我想读的,一时间从PHP命令行中的一个字符,但它好像有某种输入缓冲从某处防止这种.
考虑以下代码:
#!/usr/bin/php
<?php
echo "input# ";
while ($c = fread(STDIN, 1)) {
echo "Read from STDIN: " . $c . "\ninput# ";
}
?>
Run Code Online (Sandbox Code Playgroud)
键入"foo"作为输入(并按Enter键),我得到的输出是:
input# foo
Read from STDIN: f
input# Read from STDIN: o
input# Read from STDIN: o
input# Read from STDIN:
input#
Run Code Online (Sandbox Code Playgroud)
我期待的输出是:
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#
Run Code Online (Sandbox Code Playgroud)
(即,在键入字符时读取和处理字符).
但是,目前,只有在按下输入后才会读取每个字符.我怀疑TTY正在缓冲输入.
最终我希望能够读取按下箭头,向下箭头等按键.
dan*_*mau 32
我的解决方案是-icanon在TTY上设置模式(使用stty).例如.:
stty -icanon
Run Code Online (Sandbox Code Playgroud)
所以,现在的代码是:
#!/usr/bin/php
<?php
system("stty -icanon");
echo "input# ";
while ($c = fread(STDIN, 1)) {
echo "Read from STDIN: " . $c . "\ninput# ";
}
?>
Run Code Online (Sandbox Code Playgroud)
输出:
input# fRead from STDIN: f
input# oRead from STDIN: o
input# oRead from STDIN: o
input#
Read from STDIN:
input#
Run Code Online (Sandbox Code Playgroud)
这里给出答案的道具:
有没有办法等待(远程)终端会话按键?
有关更多信息,请参阅:http:
//www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html#AEN92
当你完成它时不要忘记恢复TTY ......
恢复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 . "'");
?>
Run Code Online (Sandbox Code Playgroud)
这是保存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");
?>
Run Code Online (Sandbox Code Playgroud)
seb*_*seb 22
这是一种适用于readline和stream函数的方法,无需弄乱tty东西.
readline_callback_handler_install('', function() { });
while (true) {
$r = array(STDIN);
$w = NULL;
$e = NULL;
$n = stream_select($r, $w, $e, null);
if ($n && in_array(STDIN, $r)) {
$c = stream_get_contents(STDIN, 1);
echo "Char read: $c\n";
break;
}
}
Run Code Online (Sandbox Code Playgroud)
在OSX上使用PHP 5.5.8进行测试.
下面的函数是@seb 答案的简化版本,可用于捕获单个字符。它不需要stream_select, 并且使用readline_callback_handler_install的固有阻塞而不是创建一个 while 循环。它还删除处理程序以允许进一步输入正常(例如 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";
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17009 次 |
| 最近记录: |