简体   繁体   English

如何将PHP数组传递给BASH脚本?

[英]How to pass a PHP array to a BASH script?

I have a php script and a bash script. 我有一个PHP脚本和一个bash脚本。 They're in the same directory. 他们在同一个目录中。 I'm running the php script from the command line which will pass an array to the bash script. 我正在从命令行运行php脚本,它将数组传递给bash脚本。 I'm trying to do the following: 我正在尝试执行以下操作:

  1. pass a PHP array to the BASH script 将PHP数组传递给BASH脚本
  2. get user input from STDIN 从STDIN获取用户输入
  3. pass the user input back to the PHP script for further processing 将用户输入传递回PHP脚本以进行进一步处理

Here's my php script: 这是我的PHP脚本:

<?php
$a=array("red","green","blue","yellow");

$string = '(' . implode(' ', $a) . ')';  // (red green blue yellow)

$user_response = shell_exec('./response.sh $string');

// do something with $user_response

?>

The BASH script is supposed to read the array from STDIN and prompt the user to select an option: BASH脚本应该从STDIN读取数组并提示用户选择一个选项:

#!/bin/bash
options=$($1);   # (red green blue yellow) but this isn't working
i=0;
echo "select an option";
for each in "${options[@]}"
do
echo "[$i] $each"
i=$((i+1))
done

echo;

read input;
echo "You picked option ${options[$input]}";
# here's where I want to pass or export the input back to the 
# php script for further processing

When I run the php script it doesn't display the array options. 当我运行php脚本时,它不显示数组选项。

I'd say the easiest would be not to try and emulate an internal bash array, but use 'normal' logic / post-processing. 我说最简单的不是尝试模拟内部bash数组,而是使用'normal'逻辑/后处理。 For example; 例如; if you simply pass implode(' ', $a) to the bash script (you should also pass it through escapeshellarg() ): 如果你只是将implode(' ', $a)传递给bash脚本(你也应该通过escapeshellarg()传递它escapeshellarg()

$a=array("red","green","blue","yellow");
$args = implode(' ', array_map('escapeshellarg', $a)); 
$user_response = shell_exec('./response.sh '. $args);

Then you can traverse the arguments in bash using 然后你可以使用bash遍历参数

for each in $*; do
  echo $each
done

The issue with your solution is that the output of the Shell Script is actually IN the PHP $response variable: 您的解决方案的问题是Shell脚本的输出实际上是PHP $response变量:

SHELL script: SHELL脚本:

#!/bin/bash
echo "Before prompt"
read -p 'Enter a value: ' input
echo "You entered $input"

PHP script: PHP脚本:

<?php
$shell = shell_exec("./t.sh");

echo "SHELL RESPONSE\n$shell\n";

Result of php t.php : php t.php结果:

$ php t.php
Enter a value: foo
SHELL RESPONSE
Before prompt
You entered foo

You captured the entire STDOUT of the Shell Script. 您捕获了Shell脚本的整个STDOUT

If you are looking to simply pass values to a shell script, the option of $option_string = implode(' ', $array_of_values); 如果您希望简单地将值传递给shell脚本,则选项$option_string = implode(' ', $array_of_values); will work to place options individually for the script. 将为脚本单独设置选项。 If you would like something a little more advanced (setting flags, assigning things, etc) try this ( https://ideone.com/oetqaY ): 如果你想要一些更先进的东西(设置标志,分配东西等)试试这个( https://ideone.com/oetqaY ):

function build_shell_args(Array $options = array(), $equals="=") {

    static $ok_chars = '/^[-0-9a-z_:\/\.]+$/i';

    $args = array();

    foreach ($options as $key => $val) if (!is_null($val) && $val !== FALSE) {

        $arg     = '';
        $key_len = 0;

        if(is_string($key) && ($key_len = strlen($key)) > 0) {

            if(!preg_match($ok_chars, $key))
                $key = escapeshellarg($key);

            $arg .= '-'.(($key_len > 1) ? '-' : '').$key;
        }

        if($val !== TRUE) {

            if((string) $val !== (string) (int) $val) {
                $val = print_r($val, TRUE);

                if(!preg_match($ok_chars, $val))
                    $val = escapeshellarg($val);

            }

            if($key_len != 0)
                $arg .= $equals;

            $arg .= $val;

        }

        if(!empty($arg))
            $args[] = $arg;

    }

    return implode(' ', $args);
}

That will be about your most comprehensive solution for passing to the command line. 这将是您传递给命令行的最全面的解决方案。

If you are instead looking for a way to prompt the user (in general), I would consider staying inside PHP. 如果您正在寻找一种方法来提示用户(一般情况下),我会考虑留在PHP中。 The most basic way is: 最基本的方法是:

print_r("$question : ");
$fp = fopen('php://stdin', 'r');
$response = fgets($fp, 1024); 

Or, to support validating the question, multi-line, and only calling on CLI: 或者,为了支持验证问题,多行,并且仅在CLI上调用:

function prompt($message = NULL, $validator = NULL, $terminator = NULL, $include_terminating_line = FALSE) {

    if(PHP_SAPI != 'cli') {
        throw new \Exception('Can not Prompt.  Not Interactive.');
    }

    $return = '';

    // Defaults to 0 or more of any character.
    $validator = !is_null($validator) ? $validator : '/^.*$/';
    // Defaults to a lonely new-line character.
    $terminator = !is_null($terminator) ? $terminator : "/^\\n$/";

    if(@preg_match($validator, NULL) === FALSE) {
        throw new Exception("Prompt Validator Regex INVALID. - '$validator'");
    }

    if(@preg_match($terminator, NULL) === FALSE) {
        throw new Exception("Prompt Terminator Regex INVALID. - '$terminator'");
    }

    $fp = fopen('php://stdin', 'r');

    $message = print_r($message,true);

    while (TRUE) {
        print_r("$message : ");

        while (TRUE) {
            $line = fgets($fp, 1024); // read the special file to get the user input from keyboard

            $terminate = preg_match($terminator, $line);
            $valid = preg_match($validator, $line);

            if (!empty($valid) && (empty($terminate) || $include_terminating_line)) {
                $return .= $line;
            }

            if (!empty($terminate)) {
                break 2;
            }

            if(empty($valid)) {
                print_r("\nInput Invalid!\n");
                break;
            }
        }
    }

    return $return;
}

Since parentheses run what's in them in a sub-shell, which isn't what I think you want... 因为括号在子shell中运行它们中的内容,这不是我想要的......

I would change this... 我会改变这个......

$string = '(' . implode(' ', $a) . ')';

To this... 对此......

$string = '"' . implode (' ', $a) . '"';

Also, use double quotes here... 另外,在这里使用双引号......

$user_response = shell_exec ("./response.sh $string");

Or break out... 或者爆发......

$user_response = shell_exec ('./response.sh ' . $string);

I would therefore also change the BASH to simply accept a single argument, a string, and split that argument into an array to get our options. 因此,我也会将BASH更改为简单地接受单个参数,字符串,并将该参数拆分为数组以获取我们的选项。

Like so... 像这样......

#!/bin/bash

IFS=' ';
read -ra options <<< "$1";
i=0;

echo "select an option";

for each in "${options[@]}"; do
    echo "[$i] $each";
    i=$((i+1));
done;

unset i;
echo;

read input;
echo "You picked option " ${options[$input]};

You can have your shell script as this: 您可以将shell脚本设置为:

#!/bin/bash
options=("$@")

i=0
echo "select an option"
for str in "${options[@]}"; do
   echo "[$i] $str"
   ((i++))
done    
echo    
read -p 'Enter an option: ' input
echo "You picked option ${options[$input]}"

Then have your PHP code as this: 然后让你的PHP代码如下:

<?php
$a=array("red","green","blue","yellow");    
$string = implode(' ', $a);    
$user_response = shell_exec("./response.sh $string");

echo "$user_response\n";
?>

However keep in mind output will be like this when running from PHP: 但是请记住,从PHP运行时输出将是这样的:

php -f test.php
Enter an option: 2
select an option
[0] red
[1] green
[2] blue
[3] yellow

You picked option blue

ie user input will come before the output from script is shown. 即用户输入将在脚本输出显示之前到来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM