在shell脚本中扩展变量

时间:2010-08-26 05:45:53

标签: shell

我有一个需要循环的查询。

query="select '$dbserver' as server;"

while read dbserver username password dbname type
do
mysql -h$dbserver -u$username -p$password $dbname -Be"$query" >> /home/develop/myreport.csv
done < $dblist

以下行正确展开。

mysql -h$dbserver -u$username -p$password $dbname -Be"select '$dbserver' as server;" >> /home/develop/myreport.csv

但是当我取出查询并将其保存在如上所示的变量中时,它会按预期停止工作并为“dbserver”提供空白值。 上面循环中提到的行不起作用。 如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

如果你想在循环中扩展查询中的'$dbserver',你可能会写:

while read dbserver username password dbname type
do
    query="select '$dbserver' as server;"
    mysql -h$dbserver -u$username -p$password $dbname -Be"$query"
done < $dblist  > /home/develop/myreport.csv

如最初编写的那样,在将任何值赋给$dbserver之前评估查询字符串,这就是输出中得到空字符串的原因。

请注意,输出重定向只执行一次 - 在done行而不是每次循环(这意味着您不需要再追加)。


使用eval通常可以在循环外部创建查询。但是,由于$dbserver的值包含在单引号内,因此结果为 hard 。如果您使用的DBMS允许在字符串周围使用双引号(与SQL标准相反),那么这适用于eval:

query='select \"$dbserver\" as server;'
echo "$query"
while read dbserver username password dbname type
do
    echo 1: "$query"
    eval echo 2: "$query"
    qval=$(eval echo "$query")
    echo mysql -h$dbserver -u$username -p$password $dbname -Be"$qval"
done

然后,您可以通过将“"”替换为“'\''”序列来对其进行调整以使用单引号:

query='select \'\''$dbserver\'\'' as server;'
echo "$query"
while read dbserver username password dbname type
do
    echo 1: "$query"
    eval echo 2: "$query"
    qval=$(eval echo "$query")
    echo mysql -h$dbserver -u$username -p$password $dbname -Be"$qval"
done
然而,那是一种引人深思的人从房间里发出尖叫的引用序列 - 请原谅我吵闹的场所! [... 稍后 ...]那更好!

说明:

  • 整个字符串在单引号内。
  • 此类字符串中没有转义字符。
  • 因此,第一个反斜杠只是反斜杠。
  • 接下来的4个字符是序列'\''
  • 这些引号中的第一个终止当前的单引号字符串。
  • 反斜杠会暂停下一个字符的特殊含义,以便该字符串包含序列中第二个单引号的实际单引号。
  • 第三个单引号启动一个新的单引号字符串。
  • 因此,在处理了第一个反斜杠和引号序列之后,该字符串包含一个反斜杠和一个引号。
  • $ dbserver此时只是普通文本。
  • 然后我们重复上一个序列,最后在字符串中使用第二个反斜杠引用对。
  • 一切都与最后一行单引号相符。

eval进程在字符串上运行了大量的扩展。反斜杠引用对仅由引号替换;插入了$dbserver的当前值。然后可以将其作为普通参数传递给命令。

eval的难点在于确保您不会出现意外的副作用。这与MySQL完全相同,后者使用反引号括起用作标记的关键字。当然,这种符号会与eval恶作剧地相互作用。但是,使用单引号围绕整个查询和反斜杠 - 反引号代替每个反引号,您可以这样做:

query='select \'\''$dbserver\'\'' as server, \`ls\` as column;'
echo "$query"
while read dbserver username password dbname type
do
    echo 1: "$query"
    eval echo 2: "$query"
    qval=$(eval echo "$query")
    echo mysql -h$dbserver -u$username -p$password $dbname -Be"$qval"
done

但我不认为可以推荐它。

答案 1 :(得分:0)

将查询分配放在循环中。在循环之前,您的变量尚未定义(即空白)

答案 2 :(得分:0)

while read -r dbserver username password dbname type
do
 query="select '$dbserver' as server;"
 mysql -h${dbserver} -u${username} -p${password} ${dbname} -Be"${query}" >> /home/develop/myreport.csv
done < $dblist