2

Is it possible to pass BASH associative arrays as argv to PHP scripts?

I have a bash script, that collects some variables to a bash associative array like this. After that, I need to send it to PHP script:

typeset -A DATA
DATA[foo]=$(some_bash_function "param1" "param2")
DATA[bar]=$(some_other_bash_function)

php script.php --data ${DATA[@]}

From PHP script, i need to access the array in following manner:

<?php

    $vars = getopt("",array(
        "data:"
    ));

    $data = $vars['data'];

    foreach ($data as $k=>$v) {
          echo "$k is $v";
    }

?>

What I've tried

Weird syntax around the --data parameter follows advice from a great post about bash arrays from Norbert Kéri how to force passed parameter as an array:

You have no way of signaling to the function that you are passing an array. You get N positional parameters, with no information about the datatypes of each.

However this sollution still does not work for associative arrays - only values are passed to the function. Norbert Kéri made a follow up article about that, however its eval based solution does not work for me, as I need to pass the actual array as a parameter.

Is the thing I'm trying to achieve impossible or is there some way? Thank you!

Update: What I am trying to accomplish

I have a few PHP configuration files of following structure:

<?php
return array(
    'option1' => 'foo',
    'option2' => 'bar'
)

My bash script collects data from user input (through bash read function) and stores them into bash associative array. This array should be later passed as an argument to PHP script.

php script.php --file "config/config.php" --data $BASH_ASSOC_ARRAY

So instead of complicated seds functions etc. I can do simple:

<?php

    $bash_input = getopt('',array('file:,data:'));
    $data = $bash_input['data'];

    $config = require($config_file);
    $config['option1'] = $data['option1'];
    $config['option2'] = $data['option2'];

    // or

    foreach ($data as $k=>$v) {
         $config[$k] = $v;
    }

    // print to config file
    file_put_contents($file, "<?php \n \n return ".var_export($config,true).";");
?>

This is used for configuring Laravel config files

9
  • Could you echo the bash array to a temporary file and then read that file? (as ugly as that would be) Commented Aug 19, 2014 at 10:50
  • Or you could pipe them into it and read the stdin? Commented Aug 19, 2014 at 10:52
  • I am a bash novice, so I need to figure out how to "echo" or "pipe" to file first and how exactly it will help my case. :) However if you would have time to elaborate to an answer ... And yes, I can work with creating files, as I source scripts from the main bash. Commented Aug 19, 2014 at 10:54
  • Do you absolutely have to use bash array? Commented Aug 19, 2014 at 10:58
  • @ZanderRootman: I'm afraid so, as I am collection the data from user input (read function) in terminal ... Commented Aug 19, 2014 at 11:00

2 Answers 2

4

Different Approach to @will's

Your bash script:

typeset -A DATA
foo=$(some_bash_function "param1" "param2")
bar=$(some_other_bash_function)

php script.php "{'data': '$foo', 'data2': '$bar'}"

PHP Script

<?php

    $vars = json_decode($argv[1]);

    $data = $vars['data'];

    foreach ($data as $k=>$v) {
          echo "$k is $v";
    }

?>

EDIT (better approach) Credit to @will

typeset -A DATA
DATA[foo]=$(some_bash_function "param1" "param2")
DATA[bar]=$(some_other_bash_function)

php script.php echo -n "{"; for key in ${!DATA[@]}; do echo - "'$key'":"'${DATA[$key]}'", | sed 's/ /,/g' ; done; echo -n "}"
Sign up to request clarification or add additional context in comments.

3 Comments

This is definately cleaner, but i think it would be much nicer if you made the json encoding automatic, something like echo -n "{"; for key in ${!assoc_array[@]}; do echo -n "'$key'":"'${assoc_array[$key]}'",; done; echo -n "}" ( i don't know if json minds the extra trailing comma at the end though, so you might need to trim that off...
Yeah the trailing comma would break the syntax. But a trim wont hurt anyone. Will update the answer quick
This is pretty much the thing I was trying to accomplish with Zander's code at the moment, yet more elegant. :) Thanks guys, you both helped me a lot!
2

this does what you want (i think) all in one bash script. You can obviously move the php file out though.

declare -A assoc_array=([key1]=value1 [key2]=value2 [key3]=value3 [key4]=value4)

#These don't come out necesarily ordered
echo ${assoc_array[@]} #echos values
echo ${!assoc_array[@]} #echos keys

echo "" > tmp

for key in ${!assoc_array[@]}
do
echo $key:${assoc_array[$key]} >> tmp   # Use some delimeter here to split the keys from the values
done

cat > file.php << EOF
<?php

    \$fileArray = explode("\n", file_get_contents("tmp"));

    \$data = array();

    foreach(\$fileArray as \$line){
        \$entry = explode(":", \$line);
        \$data[\$entry[0]] = \$entry[1];
    }

    var_dump(\$data);

?>
EOF


php file.php

the escaping is necessary in the cat block annoyingly.

2 Comments

Thank you! I will give that a try right now and get back in a minute.
Will, your approach worked, although I will probably settle for (heavily modified) @ZanderRootman's approach. Thanks a lot, you taught me a lot about temporary bash data storage to files!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.