2010-08-26 3 views
3

У меня есть запрос, который мне нужен для цикла.расширение переменных в сценарии оболочки

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 

То есть, однако, своего рода цитатой последовательности, которая посылает здравомыслящих людей от крика комнаты - простите мне момент, когда я освободить помещение грохотом! [... позже ...] Это лучше!

Объяснение:

  • Общая строка в одинарных кавычках.
  • В такой строке нет escape-символов.
  • Следовательно, первая обратная косая черта - это просто обратная косая черта.
  • Следующие 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 

Я не думаю, что это может быть рекомендовано, однако.

+0

Спасибо. Я хотел, чтобы запрос был помещен в начало скрипта и вышел из цикла, потому что его было бы легче отредактировать позже. – shantanuo

+0

@shantanuo: вы можете это сделать - см. Мой расширенный ответ. Я не уверен, что требуемая нотация дает вам пользу, которую вы ищете; сложнее получить запрос правильно. –

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

Скобки на самом деле не нужны - и разве вы не должны использовать их в задании для запроса, для согласованности, если вы используете их вообще? –

+0

означает ли это, что когда мне нужно использовать фигурные скобки, я должен изменить их все, чтобы использовать фигурные скобки, для согласованности? Скобки только на всякий случай. Это не вред. – ghostdog74

Смежные вопросы