2

I am using PHP CLI through bash shell. Please check Manipulating an array (printed by php-cli) in shell script for details.

In the following shell code I am able to echo the key- value pairs that I get from the PHP script.

IFS=":"

# parse php script output by read command
php $PWD'/test.php' | while read -r key val; do
    echo $key":"$val
done

Following is the output for this -

BASE_PATH:/path/to/project/root
db_host:localhost
db_name:database
db_user:root
db_pass:root

Now I just want to initiate dynamic variables inside the while loop so that I can use them like $BASE_PATH having value '/path/to/project/root', $db_host having 'localhost'

I come from a PHP background. I would like something like $$key = $val of PHP

Community
  • 1
  • 1
Sandeepan Nath
  • 9,501
  • 17
  • 76
  • 140

2 Answers2

4

Using eval introduces security risks that must be considered. It's safer to use declare:

# parse php script output by read command
while IFS=: read -r key val; do
    echo $key":"$val
    declare $key=$val
done < <(php $PWD'/test.php')

If you are using Bash 4, you can use associative arrays:

declare -A some_array
# parse php script output by read command
while IFS=: read -r key val; do
    echo $key":"$val
    some_array[$key]=$val
done < <(php $PWD'/test.php')

Using process substition <() and redirecting it into the done of the while loop prevents the creation of a subshell. Setting IFS for only the read command eliminates the need to save and restore its value.

Dennis Williamson
  • 324,833
  • 88
  • 366
  • 429
  • thanks for the tips but using either of your solutions, my script dies out without running anything (due to the `done < – Sandeepan Nath Jan 04 '11 at 10:09
  • @Sandeepan Nath: My examples work vary similarly to Martin's second example. If that one works for you then mine should as well. It doesn't make any sense that your test `echo` statements don't do anything. I don't understand why the redirected process substitution would cause your script to die out. – Dennis Williamson Jan 04 '11 at 15:35
  • Thanks for alerting us about the security risks related to using `eval`. You didn't actually touch on the security risks, so I did a little research. Here's a link to a site that illustrates the good and bad uses of `eval` in detail. [Eval Command And Security Issues](http://mywiki.wooledge.org/BashFAQ/048) – Dodzi Dzakuma Dec 24 '13 at 10:28
3

You may try using the eval construct in BASH:

key="BASE_PATH"
value="/path/to/project/root"
# Assign $value to variable named "BASE_PATH"
eval ${key}="${value}"

# Now you have the variable named BASE_PATH you want
# This will get you output "/path/to/project/root"
echo $BASE_PATH

Then, just use it in your loop.


EDIT: this read loop creates a sub-shell which will not allow you to use them outside of the loop. You may restructure the read loop so that the sub-shell is not created:

# get the PHP output to a variable
php_output=`php test.php`

# parse the variable in a loop without creating a sub-shell
IFS=":"
while read -r key val; do
    eval ${key}="${val}"
done <<< "$php_output"

echo $BASE_PATH
Martin Kosek
  • 388
  • 3
  • 8
  • @Martin thanks, this works but there is variable scope issue outside the while loop. I am able to echo the variable right after the eval line inside my loop, but not outside the `done` keyword of the `while` loop – Sandeepan Nath Dec 08 '10 at 07:54
  • You are right, that's because the read construct creates a sub-shell. Then the inner variables will not be visible outside of the loop. I will update the answer with alternative solution... – Martin Kosek Dec 08 '10 at 08:10
  • Sorry it does not work like this. If I separate the `while` from the `php` command (like you have done instead of `php $PWD'/test.php' | while read -r key val; do`), the while loop executes only once and `$key` and `$val` are empty. – Sandeepan Nath Dec 08 '10 at 10:02
  • also please tell me what does the `done <<< "$php_output"` statement do? I have no variable called `$php_output`. Is it a keyword? If I keep the `while` loop and the `php` command together (like in my question) and just add this `<<< "$php_output"` or `<<< "$BASE_PATH"`, the variables do not echo inside as well as outside the loop. – Sandeepan Nath Dec 08 '10 at 10:09
  • `php_output` is just a variable I declared in my second example (first command). `<<< "$php_output"` redirects the content of variable `$php_output` to the while loop What happens if you run the code I suggested, does it work? It works for me... – Martin Kosek Dec 08 '10 at 10:20