PHP的命令行扩展Readline相关函数的使用

readline 扩展函数实现了访问 GNU Readline 库的接口。这些函数提供了可编辑的命令行。一个例子是在 Bash 中允许你使用箭头按键来插入字符或者翻看历史命令。因为这个库的交互特性,这个功能在你写的 Web 程序中没多大用处,但是当你写的脚本被用在命令行中时非常有用。

Readline 扩展的安装

Readline 扩展已经加入了 PHP 的官方安装包中,如果是新的 PHP 环境,那么在编译的时候加上 --with-readline 即可。另外,我们还需要安装操作系统的 Readline 库。当然,如果已经是正常运行的 PHP ,也可以重新编译一下。

# yum install -y readline-devel
# ./congiure xxxx --with-readline

默认情况下,如果没有在编译时增加 --whit-readline ,Readline 的一些函数也是可以使用的,不过它们调用的是系统的 libedit 库。有一些函数,比如 readline_list_history() 这种函数是无法使用的。要想完整的使用 Readline 扩展的能力,那么还是需要安装操作系统的 libreadline 库(上面 yum 安装的那个 readline-devel )并在 PHP 中进行相应参数的编译安装。

基本函数操作

Readline 扩展提供的函数不多,也非常的简单易用。

读取一行

$line = readline("请输入命令:"); // 读取命令行交互信息
echo $line, PHP_EOL; // aaa

运行 PHP 代码后,我们就进入了命令提示符等待状态,并且会提示“请输入命令:”,当我们输入了 aaa 并回车之后,输入的内容就保存到了 $line 变量中。

命令历史列表相关操作

Readline 很强大的一个功能就是它自带一套命令历史记录的功能。不过这个需要我们自己手动地将命令加入到命令历史中。

$line = readline("请输入命令:"); // 读取命令行交互信息
if (!empty($line)) {
    readline_add_history($line); // 需要手动加入到命令历史记录中
}
echo $line, PHP_EOL; // aaa

$line = readline("请输入命令:");
if (!empty($line)) {
    readline_add_history($line);
}

// 命令历史记录列表
print_r(readline_list_history());
// Array
// (
//     [0] => aaa
//     [1] => bbb
// )

使用 readline_add_history() 函数,就可以将一条命令加入到命令历史记录中,然后使用 readline_list_history() 就能够打印出我们之前在交互式环境中发送过的命令记录。当然,如果只是这样简单的保存再打印那就没意思了,它还能将这些历史信息保存到外部文件进行存储。

// 将命令历史记录写入到一个文件中
readline_write_history('./readline_history');
// ./readline_history中
// _HiStOrY_V2_
// aaa
// bbb

// 清理命令历史记录
readline_clear_history();
print_r(readline_list_history());
// Array
// (
// )

// 从文件中读取命令历史记录
readline_read_history('./readline_history');
print_r(readline_list_history());
// Array
// (
//     [0] => bbb
//     [1] => bbb
// )

我们使用 readline_write_history() 函数将当前的命令历史记录保存到一个文件中,然后使用 readline_clear_history() 清理掉目前命令历史记录列表中的内容,这个时候打印 readline_list_history() 的话里面已经没有任何东西了。接着,我们再使用 readline_read_history() 将命令的历史记录从文件中加载回来进行还原。这一套功能是不是就非常有意思了,我们可以记录客户的所有命令操作,不管是安全审查还是事件回放,都非常有用。

查看 Readline 状态

// 当前命令行内部的变量信息
print_r(readline_info());
// Array
// (
//     [line_buffer] => bbb
//     [point] => 3
//     [end] => 3
//     [mark] => 0
//     [done] => 1
//     [pending_input] => 0
//     [prompt] => 请输入命令:
//     [terminal_name] => xterm-256color
//     [completion_append_character] =>
//     [completion_suppress_append] =>
//     [library_version] => 7.0
//     [readline_name] => other
//     [attempted_completion_over] => 0
// )

readline_info() 函数就比较简单了,我们可以看到最后一条交互式命令的信息,里面包括了命令输入的内容 line_buffer ,内容长度 point ,提示信息 prompt 等内容。

命令提示效果

在 Linux 等操作系统上,我们想不起一个命令的全拼没关系,只需要记住它的前几个字符然后按两个 Tab 键就可以得到相关的命令提示了。Readline 扩展库当然也为我们准备了这样的功能。

// 类似于命令行中按 Tab 键的提示效果
readline_completion_function(function ($input, $index) {
    $commands = ['next', 'exit', 'quit'];
    $matches = [];
    if ($input) {
        // 如果关键字包含在命令中,提示命令信息
        foreach ($commands as $c) {
            if (strpos($c, $input) !== false) {
                $matches[] = $c;
            }
        }
    }else{
        $matches = $commands;
    }
    return $matches;
});

// 使用 Tab 键测试一下吧
$line = trim(readline("请输入命令:"));
if (!empty($line)) {
    readline_add_history($line);
}
echo $line, PHP_EOL; // 当前输入的命令信息
// 如果命令是 exit 或者 quit ,就退出程序执行
if($line == 'exit' || $line == 'quit'){
    exit;
}

readline_completion_function() 函数会接收一个回调函数,当在交互式命令行模式下,也就是 readline 函数调用时,按下 Tab 键的时候,就会进入到这个函数的回调函数中。\$input 是当前已经输入内容的值,$index 是第几个字符。我们在这个回调函数中定义了几个默认的命令,当你键入一个 n 时直接按 Tab 键,程序就是提示出完整的 next 命令出来。当然,多个相同的字母开头的都是可以通过这个 $matches 数组返回呈现的。

此外,在这段代码中,如果我们输入了 exit 或者 quit 。将退出程序的运行。

字符回调操作相关示例

最后几个函数我们将通过一个复杂的小测试来学习。

// 输出的内容进入这个回调函数中
function rl_callback($ret)
{
    global $c, $prompting;

    echo "您输入的内容是: $ret\n";
    $c++;

    readline_add_history($ret);

    // 限制了就调用10次,也可以通过命令行输入的内容来判断,比如上面的 exit 那种进行退出
    if ($c > 10) {
        $prompting = false;
        // 移除上一个安装的回调函数句柄并且恢复终端设置
        readline_callback_handler_remove();
    } else {
        // 继续进行递归回调
        readline_callback_handler_install("[$c] 输入点什么内容: ", 'rl_callback');

    }
}

$c = 1;
$prompting = true;

// 初始化一个 readline 回调接口,然后终端输出提示信息并立即返回,需要等待 readline_callback_read_char() 函数调用后才会进入到回调函数中
readline_callback_handler_install("[$c] 输入点什么内容: ", 'rl_callback');

// 当 $prompting 为 ture 时,一直等待输入信息
while ($prompting) {
    $w = null;
    $e = null;
    $r = array(STDIN);
    $n = stream_select($r, $w, $e, null);
    if ($n && in_array(STDIN, $r)) {
        // 当一个行被接收时读取一个字符并且通知 readline 调用回调函数
        readline_callback_read_char();
    }
}

echo "结束,完成所有输入!\n";
// [1] 输入点什么内容: A
// 您输入的内容是: A
// [2] 输入点什么内容: B
// 您输入的内容是: B
// [3] 输入点什么内容: C
// 您输入的内容是: C
// [4] 输入点什么内容: D
// 您输入的内容是: D
// [5] 输入点什么内容: E
// 您输入的内容是: E
// [6] 输入点什么内容: F
// 您输入的内容是: F
// [7] 输入点什么内容: G
// 您输入的内容是: G
// [8] 输入点什么内容: H
// 您输入的内容是: H
// [9] 输入点什么内容: I
// 您输入的内容是: I
// [10] 输入点什么内容: J
// 您输入的内容是: J
// 结束,完成所有输入!

print_r(readline_list_history());
// Array
// (
//     [0] => A
//     [1] => B
//     [2] => C
//     [3] => D
//     [4] => E
//     [5] => F
//     [6] => G
//     [7] => H
//     [8] => I
//     [9] => J
// )

首先,我们先不管上面的这个自定义的函数,直接向下看到 readline_callback_read_char() 。它的作用是当一个行被接收时读取一个字符并且通知 readline 调用回调函数。也就是当一行输入完成后,键入了回车之后,这个函数将通知 Readline 组件去调用 readline_callback_handler_install() 注册的回调函数。

readline_callback_handler_install() 函数的功能是初始化一个 readline 回调接口,然后终端输出提示信息并立即返回,如果在回调函数中不进行什么操作的话,这个函数就只是输出一个提示就结束了。在我们例子中的这个回调函数 rl_callback() 中,我们根据当前接收命令的次数,判断如果接收的命令在十次内,则继续接收命令直到十次命令为止就调用 readline_callback_handler_remove() 移除上一个 readline_callback_handler_install() 安装的回调并恢复终端的默认设置。

最后执行的结果就是注释中的内容,大家也可以自己复制下代码后运行调试,只有自己进行过的调试才能理解的更加深入。

总结

Readline 很强大,而且也是 PHP 默认安装包中自带的扩展。一般被加入默认的扩展都是经过时间检验而且非常有用的扩展,大家可以根据这些内容再进行更加深入的学习并运用到实战中。

测试代码:

https://github.com/zhangyue0503/dev-blog/

以上就是PHP的命令行扩展Readline相关函数的使用的详细内容,更多关于PHP 命令行扩展Readline的使用的资料请关注我们其它相关文章!

(0)

相关推荐

  • php根据命令行参数生成配置文件详解

    像npm, composer等工具,在开始使用的使用,都需要初始化项目,生成一个项目的配置文件.这种功能的原理是怎么实现的呢? 比如: D:\>npm init --yes Wrote to D:\package.json: { "name": "", "version": "1.0.0", "description": "", "main": "in

  • 如何通过Linux命令行使用和运行PHP脚本

    下面通过图文并茂的方式给大家分享下通过Linux命令使用和运行PHP脚本. PHP是一个开源服务器端脚本语言,最初这三个字母代表的是"Personal Home Page",而现在则代表的是"PHP:Hypertext Preprocessor",它是个递归首字母缩写.它是一个跨平台脚本语言,深受C.C++和Java的影响. 在 Linux 命令行中运行 PHP 代码 PHP的语法和C.Java以及带有一些PHP特性的Perl变成语言中的语法十分相似,它当下大约正被

  • 实例讲解yii2.0在php命令行中运行的步骤

    Yii中的资源是和Web页面相关的文件,可为CSS文件,JavaScript文件,图片或视频等,资源放在Web可访问的目录下,直接被Web服务器调用. 有时候有些功能需要做到计划任务中去,因此就需要yii能用php命令去执行.yii2.0是支持php命令行运行的,操作方法如下: 在yii根目录下面有个"yii"文件(不是"yii.bat"),这个文件就是入口.然后"commands"目录下会默认有个"HelloController.ph

  • php生成curl命令行的方法

    本文实例讲述了php生成curl命令行的方法.分享给大家供大家参考,具体如下: 示例: curl "http://localhost/other/serverInfo.php?dd=ddd" -H "Host:localhost" -H "Connection:keep-alive" -H "Cache-Control:max-age=0" -H "Accept:text/html,application/xhtml

  • php命令行写shell实例详解

    php 可以像java perl python 那样运行,今天发现如果我早早知道这个,或许我不会去学习java 和 python 当年学java不过为了一个程序放在服务器上,不停的跑啊跑,原来 php 也可以. php -h Usage: php [options] [-f] <file> [--] [args...] php [options] -r <code> [--] [args...] php [options] [-B <begin_code>] -R &l

  • PHP如何获取命令行参数

    使用 PHP 开发的同学多少都会接触过 CLI 命令行.经常会有一些定时任务或者一些脚本直接使用命令行处理会更加的方便,有些时候我们会需要像网页的 GET . POST 一样为这些命令行脚本提供参数.比如在针对某些日期做统计的脚本,就需要传递一个日期给它,这样我们就统计指定日期的一些数据.这类需求应该非常常见,那么,我们都是如何来接收这些命令行的参数的呢?今天,就来介绍一下这方面的内容. $argv 获得所有空格分隔的参数列表 这个变量估计是大家用得比较多的一个接参变量了.它是 PHP 为我们准

  • 利用PHP命令行模式采集股票趋势信息

    话不多说,下面直接来看实现代码. 主要函数只有一个类实现(stock.class.php): <?php class StockClass{ public $stockId; public function __construct($stockId){ $this -> stockId = $stockId; } private function getUrl(){ return "http://stockpage.10jqka.com.cn/" . $this ->

  • php命令行模式代码实例详解

    php全集行模式,即php-cli,官方文档中称为: CLI SAPI(Server Application Programming Interface,服务端应用编程端口).听着挺复杂.其实是因为php原本为服务器端的脚本语言,所以引申出这个叫法. 与服务端模式的不同 服务端模式主要有两种工作方式: 作为web server的模式方式或作为一个cgi可执行程序. 前者,比如作为apach中的一个模块(如:php5apache2.dll); 后者作为可执行程序,如php-cig. 现在的替代者为

  • 基于命令行执行带参数的php脚本并取得参数的方法

    本文分析了基于命令行执行带参数的php脚本并取得参数的方法.分享给大家供大家参考,具体如下: 一.为什么我们要在命令行下运行php脚本呢? 个人理解,主要有二个原因: 1. 利用crontab去跑php,可以给服务器减压,当然在这里有一个条件,就是实时性要求不高.比如:sns中的好友动态,这个实时要求不高,但是数据量比较大,这个时候定时跑的话,会给web服务器,数据库服务器分担不小的压力. 2. 就是我们要定时去完成某一事情,比如:我要删除一个月前,用户留言,这个时候,写的php脚本在cront

  • 命令行执行php脚本中的$argv和$argc配置方法

    在实际工作中有可能会碰到需要在nginx命令行执行php脚本的时候,当然你可以去配置一个conf用外网访问. 在nginx命令行中 使用 php index.php 就可以执行这个index.php脚本了,但是怎么传递参数呢?那就要用到$argv和$aegc了.不用开启什么设置 直接在脚本中使用,类似于http传值中的$_POST和$_GET.. 在index.php插入以下菜吗 <?php echo $argv[0]; echo "\n"; var_dump($argv[1])

  • php web环境和命令行环境下查找php.ini的位置

    php.ini 是php运行的配置文件,不是一个必须使用的文件.不过通常php程序运行都需要加载php.ini文件. php.ini 提供了一些重要的参数.比如运行的时候出错的时候是否报错,运行的内存最大是多少 和一些php扩展的配置信息. php.ini 在哪里可以找到 如果源代码安装的时候,有个配置的参数 --with-config-file-path 可以指定位置.对于安装好的php程序向获取php.ini的位置可以查看php的信息. 1. web环境通过phpinfo() 查看php.i

随机推荐