【问题标题】:Initiating dynamic variables (variable variables) in bash shell script在 bash shell 脚本中启动动态变量(变量)
【发布时间】:2010-12-08 07:25:42
【问题描述】:

我正在通过 bash shell 使用 PHP CLI。详情请查看Manipulating an array (printed by php-cli) in shell script

在下面的 shell 代码中,我可以回显从 PHP 脚本获得的 key- value 对。

IFS=":"

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

以下是这个的输出 -

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

现在我只想在 while 循环中启动动态变量,这样我就可以使用它们,例如 $BASE_PATH 具有值 '/path/to/project/root'$db_host 具有 'localhost'

我来自 PHP 背景。我想要 PHP 的 $$key = $val 之类的东西

【问题讨论】:

    标签: linux bash shell variables


    【解决方案1】:

    使用eval 会引入必须考虑的安全风险。使用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')
    

    如果您使用的是 Bash 4,则可以使用关联数组:

    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')
    

    使用进程替换&lt;() 并将其重定向到while 循环的done 可防止创建子shell。仅为read 命令设置 IFS,无需保存和恢复其值。

    【讨论】:

    • 感谢您的提示,但使用您的任何一种解决方案,我的脚本都会在没有运行任何东西的情况下消失(由于 done &lt; &lt;(php $PWD'/test.php') 部分)。我尝试在 while 条件之前放置 echo "before",在循环之后放置 echo "after" read simply。但没有回显,脚本也不会提示任何用户输入。
    • @Sandeepan Nath:我的示例工作方式与 Martin 的第二个示例类似。如果那个对你有用,那么我的也应该。您的测试 echo 语句没有做任何事情是没有任何意义的。我不明白为什么重定向的进程替换会导致你的脚本消失。
    • 感谢您提醒我们有关使用 eval 的安全风险。您实际上并没有涉及安全风险,所以我做了一些研究。这是一个网站链接,详细说明了eval 的好坏用途。 Eval Command And Security Issues
    【解决方案2】:

    您可以尝试在 BASH 中使用eval 构造:

    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
    

    然后,在你的循环中使用它。


    编辑:这个读取循环创建一个子shell,它不允许你在循环之外使用它们。您可以重组读取循环,以便不创建子外壳:

    # 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 谢谢,这可行,但在 while 循环之外存在变量范围问题。我可以在循环内的 eval 行之后回显变量,但不能在 while 循环的 done 关键字之外
    • 你是对的,那是因为读取构造创建了一个子外壳。然后内部变量将在循环之外不可见。我将用替代解决方案更新答案...
    • 对不起,它不能这样工作。如果我将whilephp 命令分开(就像你所做的而不是php $PWD'/test.php' | while read -r key val; do),while 循环只执行一次,$key$val 为空。
    • 还请告诉我done &lt;&lt;&lt; "$php_output" 语句的作用是什么?我没有名为$php_output 的变量。是关键字吗?如果我将while 循环和php 命令放在一起(就像在我的问题中一样)并添加此&lt;&lt;&lt; "$php_output"&lt;&lt;&lt; "$BASE_PATH",则变量不会在循环内部和外部回显。
    • php_output 只是我在第二个示例(第一个命令)中声明的变量。 &lt;&lt;&lt; "$php_output" 将变量 $php_output 的内容重定向到 while 循环 如果你运行我建议的代码会发生什么,它有效吗?它对我有用...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 2015-04-03
    • 2021-10-17
    • 2012-08-31
    • 2021-11-04
    • 2021-08-22
    • 2014-12-02
    相关资源
    最近更新 更多