簡體   English   中英

使用 PHP 的交互式 shell

[英]Interactive shell using PHP

只是想知道,是否可以單獨使用 PHP 創建交互式 shell。 我的意思是像你有數據庫、python 等的東西。

如果是,如何?

是的,這是可能的。 為了具有交互性,程序必須能夠等待並讀取來自stdin 的用戶輸入。 在PHP中,你可以通過打開文件描述符從標准輸入讀取'php://stdin' 摘自不同問題的答案,以下是 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),你可以使用 ncurses

由於這個問題已經被提出和回答,一個更好的解決方案被添加到 PHP 中 在所有最新的 PHP 版本中,您可以輕松地獲得用戶輸入,如下所示:

$input = fgets(STDIN);

我理解您的問題的方式是,您只希望 PHP 解釋器在命令行上運行,以便它評估您鍵入的任何 PHP 代碼。 我一直使用 Python 的這個特性來測試代碼片段。 在這種情況下,我相信您正在尋找的答案是執行(從命令行):

php -a

假設 PHP 在你的路徑中,這會讓你進入 PHP 解釋器,就像我的一樣:

$ php -a
Interactive shell

php > 

從那里您可以開始評估任意 PHP 表達式並查看結果:

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

這是對此的擴展。 我添加了一個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);

我知道提問者不想要第二個選項,但是對於那些像我一樣想要第二個選項的人,除了phpsh ,PHP 也有它 自己的 shell

只需運行php -a

由於 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可以使用!isset進行測試。

還有內置的readline_add_history()將用戶輸入存儲到一個對象中,其中可以通過名稱直接檢索值(為了代碼清晰,這很好):

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

構建真正復雜的東西非常有用!

了解如何捕捉和發送 POSIX 信號

PHP 函數 readline()

從您是要單獨使用 PHP 創建 shell 還是要交互式 shell 處理 PHP 命令的問題中,並不完全清楚。 我將假設后者,在這種情況下,一個例子是phpsh ,它顯然是在 Facebook 創建的,但用 python 編寫。

查看:

https://github.com/shaneharter/sheldon

很容易上手。 它包括 Symfony2 和 Zend Framework 庫,它們執行許多基本的控制台 I/O 工作,並為您提供圍繞 Command 對象(使用正則表達式路由)和 Contexts(保持不可變狀態)構建的更高級別的抽象。

我喜歡的一件事是“開箱即用”您的應用程序可以作為交互式 shell 運行,也可以作為標准腳本運行,您可以從命令行運行,指定命令,傳遞任何參數,以及當命令完成應用程序退出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM