2010-08-26 143 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