主頁(yè) > 知識(shí)庫(kù) > PHP的命令行擴(kuò)展Readline相關(guān)函數(shù)的使用

PHP的命令行擴(kuò)展Readline相關(guān)函數(shù)的使用

熱門標(biāo)簽:銀行業(yè)務(wù) Linux服務(wù)器 服務(wù)器配置 Mysql連接數(shù)設(shè)置 科大訊飛語(yǔ)音識(shí)別系統(tǒng) 電子圍欄 阿里云 團(tuán)購(gòu)網(wǎng)站

readline 擴(kuò)展函數(shù)實(shí)現(xiàn)了訪問(wèn) GNU Readline 庫(kù)的接口。這些函數(shù)提供了可編輯的命令行。一個(gè)例子是在 Bash 中允許你使用箭頭按鍵來(lái)插入字符或者翻看歷史命令。因?yàn)檫@個(gè)庫(kù)的交互特性,這個(gè)功能在你寫的 Web 程序中沒(méi)多大用處,但是當(dāng)你寫的腳本被用在命令行中時(shí)非常有用。

Readline 擴(kuò)展的安裝

Readline 擴(kuò)展已經(jīng)加入了 PHP 的官方安裝包中,如果是新的 PHP 環(huán)境,那么在編譯的時(shí)候加上 --with-readline 即可。另外,我們還需要安裝操作系統(tǒng)的 Readline 庫(kù)。當(dāng)然,如果已經(jīng)是正常運(yùn)行的 PHP ,也可以重新編譯一下。

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

默認(rèn)情況下,如果沒(méi)有在編譯時(shí)增加 --whit-readline ,Readline 的一些函數(shù)也是可以使用的,不過(guò)它們調(diào)用的是系統(tǒng)的 libedit 庫(kù)。有一些函數(shù),比如 readline_list_history() 這種函數(shù)是無(wú)法使用的。要想完整的使用 Readline 擴(kuò)展的能力,那么還是需要安裝操作系統(tǒng)的 libreadline 庫(kù)(上面 yum 安裝的那個(gè) readline-devel )并在 PHP 中進(jìn)行相應(yīng)參數(shù)的編譯安裝。

基本函數(shù)操作

Readline 擴(kuò)展提供的函數(shù)不多,也非常的簡(jiǎn)單易用。

讀取一行

$line = readline("請(qǐng)輸入命令:"); // 讀取命令行交互信息
echo $line, PHP_EOL; // aaa

運(yùn)行 PHP 代碼后,我們就進(jìn)入了命令提示符等待狀態(tài),并且會(huì)提示“請(qǐng)輸入命令:”,當(dāng)我們輸入了 aaa 并回車之后,輸入的內(nèi)容就保存到了 $line 變量中。

命令歷史列表相關(guān)操作

Readline 很強(qiáng)大的一個(gè)功能就是它自帶一套命令歷史記錄的功能。不過(guò)這個(gè)需要我們自己手動(dòng)地將命令加入到命令歷史中。

$line = readline("請(qǐng)輸入命令:"); // 讀取命令行交互信息
if (!empty($line)) {
    readline_add_history($line); // 需要手動(dòng)加入到命令歷史記錄中
}
echo $line, PHP_EOL; // aaa

$line = readline("請(qǐng)輸入命令:");
if (!empty($line)) {
    readline_add_history($line);
}

// 命令歷史記錄列表
print_r(readline_list_history());
// Array
// (
//     [0] => aaa
//     [1] => bbb
// )

使用 readline_add_history() 函數(shù),就可以將一條命令加入到命令歷史記錄中,然后使用 readline_list_history() 就能夠打印出我們之前在交互式環(huán)境中發(fā)送過(guò)的命令記錄。當(dāng)然,如果只是這樣簡(jiǎn)單的保存再打印那就沒(méi)意思了,它還能將這些歷史信息保存到外部文件進(jìn)行存儲(chǔ)。

// 將命令歷史記錄寫入到一個(gè)文件中
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() 函數(shù)將當(dāng)前的命令歷史記錄保存到一個(gè)文件中,然后使用 readline_clear_history() 清理掉目前命令歷史記錄列表中的內(nèi)容,這個(gè)時(shí)候打印 readline_list_history() 的話里面已經(jīng)沒(méi)有任何東西了。接著,我們?cè)偈褂?readline_read_history() 將命令的歷史記錄從文件中加載回來(lái)進(jìn)行還原。這一套功能是不是就非常有意思了,我們可以記錄客戶的所有命令操作,不管是安全審查還是事件回放,都非常有用。

查看 Readline 狀態(tài)

// 當(dāng)前命令行內(nèi)部的變量信息
print_r(readline_info());
// Array
// (
//     [line_buffer] => bbb
//     [point] => 3
//     [end] => 3
//     [mark] => 0
//     [done] => 1
//     [pending_input] => 0
//     [prompt] => 請(qǐng)輸入命令:
//     [terminal_name] => xterm-256color
//     [completion_append_character] =>
//     [completion_suppress_append] =>
//     [library_version] => 7.0
//     [readline_name] => other
//     [attempted_completion_over] => 0
// )

readline_info() 函數(shù)就比較簡(jiǎn)單了,我們可以看到最后一條交互式命令的信息,里面包括了命令輸入的內(nèi)容 line_buffer ,內(nèi)容長(zhǎng)度 point ,提示信息 prompt 等內(nèi)容。

命令提示效果

在 Linux 等操作系統(tǒng)上,我們想不起一個(gè)命令的全拼沒(méi)關(guān)系,只需要記住它的前幾個(gè)字符然后按兩個(gè) Tab 鍵就可以得到相關(guān)的命令提示了。Readline 擴(kuò)展庫(kù)當(dāng)然也為我們準(zhǔn)備了這樣的功能。

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

// 使用 Tab 鍵測(cè)試一下吧
$line = trim(readline("請(qǐng)輸入命令:"));
if (!empty($line)) {
    readline_add_history($line);
}
echo $line, PHP_EOL; // 當(dāng)前輸入的命令信息
// 如果命令是 exit 或者 quit ,就退出程序執(zhí)行
if($line == 'exit' || $line == 'quit'){
    exit;
}

readline_completion_function() 函數(shù)會(huì)接收一個(gè)回調(diào)函數(shù),當(dāng)在交互式命令行模式下,也就是 readline 函數(shù)調(diào)用時(shí),按下 Tab 鍵的時(shí)候,就會(huì)進(jìn)入到這個(gè)函數(shù)的回調(diào)函數(shù)中。\$input 是當(dāng)前已經(jīng)輸入內(nèi)容的值,$index 是第幾個(gè)字符。我們?cè)谶@個(gè)回調(diào)函數(shù)中定義了幾個(gè)默認(rèn)的命令,當(dāng)你鍵入一個(gè) n 時(shí)直接按 Tab 鍵,程序就是提示出完整的 next 命令出來(lái)。當(dāng)然,多個(gè)相同的字母開(kāi)頭的都是可以通過(guò)這個(gè) $matches 數(shù)組返回呈現(xiàn)的。

此外,在這段代碼中,如果我們輸入了 exit 或者 quit 。將退出程序的運(yùn)行。

字符回調(diào)操作相關(guān)示例

最后幾個(gè)函數(shù)我們將通過(guò)一個(gè)復(fù)雜的小測(cè)試來(lái)學(xué)習(xí)。

// 輸出的內(nèi)容進(jìn)入這個(gè)回調(diào)函數(shù)中
function rl_callback($ret)
{
    global $c, $prompting;

    echo "您輸入的內(nèi)容是: $ret\n";
    $c++;

    readline_add_history($ret);

    // 限制了就調(diào)用10次,也可以通過(guò)命令行輸入的內(nèi)容來(lái)判斷,比如上面的 exit 那種進(jìn)行退出
    if ($c > 10) {
        $prompting = false;
        // 移除上一個(gè)安裝的回調(diào)函數(shù)句柄并且恢復(fù)終端設(shè)置
        readline_callback_handler_remove();
    } else {
        // 繼續(xù)進(jìn)行遞歸回調(diào)
        readline_callback_handler_install("[$c] 輸入點(diǎn)什么內(nèi)容: ", 'rl_callback');

    }
}

$c = 1;
$prompting = true;

// 初始化一個(gè) readline 回調(diào)接口,然后終端輸出提示信息并立即返回,需要等待 readline_callback_read_char() 函數(shù)調(diào)用后才會(huì)進(jìn)入到回調(diào)函數(shù)中
readline_callback_handler_install("[$c] 輸入點(diǎn)什么內(nèi)容: ", 'rl_callback');

// 當(dāng) $prompting 為 ture 時(shí),一直等待輸入信息
while ($prompting) {
    $w = null;
    $e = null;
    $r = array(STDIN);
    $n = stream_select($r, $w, $e, null);
    if ($n  in_array(STDIN, $r)) {
        // 當(dāng)一個(gè)行被接收時(shí)讀取一個(gè)字符并且通知 readline 調(diào)用回調(diào)函數(shù)
        readline_callback_read_char();
    }
}

echo "結(jié)束,完成所有輸入!\n";
// [1] 輸入點(diǎn)什么內(nèi)容: A
// 您輸入的內(nèi)容是: A
// [2] 輸入點(diǎn)什么內(nèi)容: B
// 您輸入的內(nèi)容是: B
// [3] 輸入點(diǎn)什么內(nèi)容: C
// 您輸入的內(nèi)容是: C
// [4] 輸入點(diǎn)什么內(nèi)容: D
// 您輸入的內(nèi)容是: D
// [5] 輸入點(diǎn)什么內(nèi)容: E
// 您輸入的內(nèi)容是: E
// [6] 輸入點(diǎn)什么內(nèi)容: F
// 您輸入的內(nèi)容是: F
// [7] 輸入點(diǎn)什么內(nèi)容: G
// 您輸入的內(nèi)容是: G
// [8] 輸入點(diǎn)什么內(nèi)容: H
// 您輸入的內(nèi)容是: H
// [9] 輸入點(diǎn)什么內(nèi)容: I
// 您輸入的內(nèi)容是: I
// [10] 輸入點(diǎn)什么內(nèi)容: J
// 您輸入的內(nèi)容是: J
// 結(jié)束,完成所有輸入!

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
// )

首先,我們先不管上面的這個(gè)自定義的函數(shù),直接向下看到 readline_callback_read_char() 。它的作用是當(dāng)一個(gè)行被接收時(shí)讀取一個(gè)字符并且通知 readline 調(diào)用回調(diào)函數(shù)。也就是當(dāng)一行輸入完成后,鍵入了回車之后,這個(gè)函數(shù)將通知 Readline 組件去調(diào)用 readline_callback_handler_install() 注冊(cè)的回調(diào)函數(shù)。

readline_callback_handler_install() 函數(shù)的功能是初始化一個(gè) readline 回調(diào)接口,然后終端輸出提示信息并立即返回,如果在回調(diào)函數(shù)中不進(jìn)行什么操作的話,這個(gè)函數(shù)就只是輸出一個(gè)提示就結(jié)束了。在我們例子中的這個(gè)回調(diào)函數(shù) rl_callback() 中,我們根據(jù)當(dāng)前接收命令的次數(shù),判斷如果接收的命令在十次內(nèi),則繼續(xù)接收命令直到十次命令為止就調(diào)用 readline_callback_handler_remove() 移除上一個(gè) readline_callback_handler_install() 安裝的回調(diào)并恢復(fù)終端的默認(rèn)設(shè)置。

最后執(zhí)行的結(jié)果就是注釋中的內(nèi)容,大家也可以自己復(fù)制下代碼后運(yùn)行調(diào)試,只有自己進(jìn)行過(guò)的調(diào)試才能理解的更加深入。

總結(jié)

Readline 很強(qiáng)大,而且也是 PHP 默認(rèn)安裝包中自帶的擴(kuò)展。一般被加入默認(rèn)的擴(kuò)展都是經(jīng)過(guò)時(shí)間檢驗(yàn)而且非常有用的擴(kuò)展,大家可以根據(jù)這些內(nèi)容再進(jìn)行更加深入的學(xué)習(xí)并運(yùn)用到實(shí)戰(zhàn)中。

測(cè)試代碼:

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

以上就是PHP的命令行擴(kuò)展Readline相關(guān)函數(shù)的使用的詳細(xì)內(nèi)容,更多關(guān)于PHP 命令行擴(kuò)展Readline的使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • PHP的runkit擴(kuò)展如何使用
  • PHP緩存系統(tǒng)APCu擴(kuò)展的使用
  • 如何動(dòng)態(tài)查看及加載PHP擴(kuò)展
  • Thinkphp使用Zxing擴(kuò)展庫(kù)解析二維碼內(nèi)容圖文講解
  • PHP擴(kuò)展安裝方法步驟解析
  • PHP 擴(kuò)展Memcached命令用法實(shí)例總結(jié)
  • PHP擴(kuò)展類型及安裝方式解析
  • 如何使用Zephir輕松構(gòu)建PHP擴(kuò)展

標(biāo)簽:廣元 衡水 大理 萍鄉(xiāng) 蚌埠 棗莊 衢州 江蘇

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PHP的命令行擴(kuò)展Readline相關(guān)函數(shù)的使用》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266