如果你想在循环内部扩展查询中的'$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
的值被包含在单引号内,所以这变得困难。如果您正在使用的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
虽然我不认为可以推荐这个,但是。