2015-09-22 2 views
11

У меня есть скрипт php и скрипт bash. Они находятся в одном каталоге. Я запускаю php-скрипт из командной строки, который передаст массив в сценарий bash. Я пытаюсь сделать следующее:Как передать массив PHP в BASH-скрипт?

  1. передать PHP массив в скрипт BASH
  2. получить пользовательский ввод из STDIN
  3. передать пользовательский ввод обратно в 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 

?> 

сценарий BASH должен прочитать массив из STDIN и подсказать нам er, чтобы выбрать опцию:

#!/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 

Когда я запускаю скрипт php, он не отображает параметры массива.

+2

Не вы хотите '$ string' быть передан как его фактическое значение? В настоящее время он передается как строка _ $ string_ значение. Используйте двойные кавычки в 'shell_exec (" ./ response.sh $ string ");' поэтому PHP может его проанализировать. Что касается Баша, я не имею понятия, поэтому я не стану его ответом. – DeDee

+0

Я получаю следующую ошибку, когда я использую двойные кавычки: 'sh: 1: Синтаксическая ошибка: слово неожиданное (ожидающее") ")' – cooldood3490

+0

Я знаю, что вы уже выбрали ответ, но мне было бы интересно, если вы ищете for - это просто возможность выбора параметров, если, возможно, вас больше интересует приглашение PHP-скрипта для ввода. – Mike

ответ

2

Вы можете иметь свой скрипт, как это:

#!/bin/bash 
options=("[email protected]") 

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]}" 

Тогда есть свой PHP код, как это:

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

echo "$user_response\n"; 
?> 

Однако держать в вывод будет таким, как при работе с PHP:

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

You picked option blue 

Введем пользовательский ввод до того, как будет показан вывод из сценария.

+0

Поскольку пользовательский ввод поступает до вывода из сценария bash, это может быть проще, если я должен сделать все это в скрипте php. еще раз спасибо. – cooldood3490

+0

Это происходит потому, что переменная PHP '$ user_response' содержит содержимое' STDOUT', а не фактическое значение, на которое ответил пользователь. – Mike

3

Я бы сказал, что самым простым было бы не пытаться эмулировать внутренний массив bash, а использовать «нормальную» логику/пост-обработку. Например; если вы просто передать implode(' ', $a) в скрипт Баш (вы должны также пройти через escapeshellarg()):

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

Затем вы можете пройти аргументы в Баш с помощью

for each in $*; do 
    echo $each 
done 
+1

Как выглядел бы скрипт bash? Когда вызывается 'response.sh', он должен отображать параметры на терминале и запрашивать пользователя для ввода, а затем передавать вход обратно в скрипт php. – cooldood3490

+0

Я не собираюсь делать домашнее задание; если мой ответ поможет вам в вашем конкретном вопросе; пожалуйста, примите этот ответ и выполните сам сценарий. – Sjon

2

С Скобки работать, что в них в суб-оболочка, которая является не то, что я думаю, что вы хотите ...

Я хотел бы изменить это ...

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

Для этого ...

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

Кроме того, используйте двойные кавычки здесь ...

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

Или разразится ...

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

Поэтому я хотел бы также изменить BASH просто принять один аргумент, строку и разделить этот аргумент на массив, чтобы получить наши параметры.

Как так ...

#!/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]}; 
3

Проблема с вашим решением является то, что выход Shell Script фактически в переменной PHP $response:

SHELL сценарий:

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

PHP скрипт:

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

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

Результат от php t.php:

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

Вы сняли весь STDOUT сценарий Shell.

Если вы хотите просто передать значения сценарию оболочки, то опция $option_string = implode(' ', $array_of_values); будет работать, чтобы поместить параметры для сценария отдельно. Если вы хотите что-то немного более продвинутое (установка флагов, назначение вещей, и т.д.) попробуйте это (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); 
} 

Это будет о вашем наиболее полном решении для перехода к командной строке.

Если вы ищете способ запросить пользователя (в общем), я бы подумал о том, чтобы оставаться внутри PHP. Самый простой способ:

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

Или, для поддержки проверки на вопрос, Многоканальный, и только вызов на 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; 
} 
Смежные вопросы