使用PHP的交互式shell

时间:2011-04-26 17:22:12

标签: php shell interactive

只是想知道,是否可以单独使用PHP来创建交互式shell。我的意思是像数据库,python等一样。

如果是,怎么样?

8 个答案:

答案 0 :(得分:38)

是的,这是可能的。为了实现交互,程序必须能够等待并读入来自 stdin 的用户输入。在PHP中,您可以通过打开'php://stdin'的文件描述符来读取 stdin 。摘自an answer to different question,这是PHP中交互式用户提示的示例(当然,从命令行运行时):

echo "Continue? (Y/N) - ";

$stdin = fopen('php://stdin', 'r');
$response = fgetc($stdin);
if ($response != 'Y') {
   echo "Aborted.\n";
   exit;
}

当然,要获得完整的输入线而不是单个字符,您需要fgets()而不是fgetc()。根据您的程序/ shell将执行的操作,整个程序可能被构造为一个大的连续循环。希望这能让您了解如何开始。如果你想真的花哨(CLI伪GUI),你可以use ncurses

答案 1 :(得分:24)

由于已经提出并回答了这个问题,已经为PHP添加了更好的解决方案。在所有最近的PHP版本中,您可以轻松获得用户输入:

$input = fgets(STDIN);

答案 2 :(得分:5)

我理解您的问题的方式只是希望PHP解释器在命令行上运行,以便它将评估您键入的任何PHP代码。我一直使用Python的这个功能来测试代码片段。在这种情况下,我相信你要找的答案是执行(从命令行):

php -a

假设PHP在您的路径中,这将使您进入PHP解释器,就像我的一样:

$ php -a
Interactive shell

php > 

从那里开始评估任意PHP表达式并查看结果:

php > $a = 'abcdef';
php > echo strlen($a);
6

答案 3 :(得分:2)

以下是对此的扩展。我已添加isCLI()检查,以防您在CLI和Web服务器上运行脚本。否则服务器可以使用我的函数循环。此解决方案将提示用户,检查输入,并在必要时重新提示用户输入固定输入。我rtrim()输入,因为如果用户使用return来提交他们的条目,那么可以将其附加到条目中。验证不是必需的,只是在这种情况下不传递函数。

function isCLI() {
    return (php_sapi_name() === 'cli' OR defined('STDIN'));
}

function userPrompt($message, $validator=null) {
    if (!isCLI()) return null;

    print($message);
    $handle = fopen ('php://stdin','r');
    $line = rtrim(fgets($handle), "\r\n");

    if (is_callable($validator) && !call_user_func($validator, $line)) {
        print("Invalid Entry.\r\n");
        return userPrompt($message, $validator);
    } else {
        print("Continuing...\r\n");
        return $line;
    }
}

// Example =====================

function validateSetLangCode($str) {
    return preg_match("/^[A-Z0-9]{3}-[A-Z]{2}$/", $str);
}

$code = userPrompt("Please enter the set / language codes. Use the format 'SET-EN', where SET is the three-letter set code and EN is the two-letter lang code. \r\n", 'validateSetLangCode') ?: 'SET-EN';
var_dump($code);

答案 4 :(得分:1)

关于是否要单独使用PHP创建shell,或者是否希望交互式shell处理PHP命令,这个问题并不完全清楚。我将假设后者,在这种情况下,一个例子是phpsh,显然是在Facebook上创建的,但是是用python编写的。

答案 5 :(得分:1)

我知道提问者不想要第二个选项,但对于那些想要第二个选项的人,除了phpsh之外,PHP还有own shell

只需运行php -a

答案 6 :(得分:0)

退房:

https://github.com/shaneharter/sheldon

入门很容易。它包括Symfony2和Zend Framework库,它们执行许多基本的控制台I / O工作,并为您提供围绕Command对象(带有正则表达式路由)和上下文(持有不可变状态)的更高级别的抽象。

我喜欢的一件事是“开箱即用”您的应用程序既可以作为交互式shell运行,也可以作为可以从命令行运行的标准脚本运行,指定命令,传递任何参数,以及命令完成后,应用程序退出。

答案 7 :(得分:0)

由于PHP有一个内置的 unix only 函数readline()来完成这个,所以留下以下注释。

我们可以使用readline的结果并将其保存到var。

#!/usr/bin/php
<?php
$user = readline("List dir [l] | Say hello [h] | exit [q]: ");

if ($user === "l"){ system("ls"); }

if ($user === "h"){ echo "Hello!"; }

if ($user === "q"){ exit; }

echo "\nThanks!";

示例输出:

l ls结果

h«你好»

q退出

ctrl+c退出。

带空输入的

ctrl+d,继续下一个序列。 “谢谢”。 $user已定义且为空,无错误。

ctrl+d有一些输入:没有动作。还在等待输入。

ctrl+m继续并获取$user中的当前输入。

ctrl+j继续并采用$user中的当前输入,行为与ctrl+m相同。

Return继续下一个序列«谢谢»。 $user可以保持空白,没有错误。

ctrl+z可用于取消循环并移至顶部循环。如果未在此范围中定义var,则将取消设置$user

根据输入,我们可以使用!empty定义空值或进行更多手术测试(readline响应可以是多个字符)。

如果尚未询问,则可以使用$user对{p> !isset进行测试。

还有内置的readline_add_history()将用户输入存储到对象中,其中的值可以通过名称直接检索(Nice代码清晰度):

readline_add_history($user);
print_r(readline_list_history());
print_r(readline_user());

构建真正复杂的东西非常有用!

http://php.net/manual/en/function.readline.php