2010-08-26 142 views
3

我有一个查询需要循环。在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”空值。 上面的循环中提到的行不起作用。 如何解决此问题?

回答

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。如果数据库管理系统使用的是允许使用双引号的字串,(违反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作为标记的关键字的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 

我不认为它可以被推荐,虽然。

+0

谢谢。我希望将查询置于脚本的顶部并避开循环,因为稍后可以更轻松地进行编辑。 – shantanuo 2010-08-26 06:19:23

+0

@shantanuo:你可以做到 - 看到我的扩展答案。我不确定所需的符号是否能为您提供您所寻求的好处;查询的正确性比较复杂。 – 2010-08-26 13:59:50

0

将查询分配放入循环中。在循环之前的变量还没有(即空白)定义

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 
+0

大括号并不是真的必要的 - 如果你使用它们,你不应该在分配中使用它们来进行查询,以保持一致性? – 2010-08-26 06:04:22

+0

是否意味着当我需要使用大括号时,我必须将它们全部更改为使用大括号以保持一致性?大括号在那里,以防万一。它没有伤害。 – ghostdog74 2010-08-26 06:33:21