2011-05-07 3 views
12

je besoin d'un script bash qui peut récupérer des données MySQL à partir d'une base de données à distance. En fait, je l'ai fait, mais ce que j'ai besoin de faire maintenant est de faire une boucle dans les enregistrements d'une manière ou d'une autre et de passer une variable à un autre fichier bash. Voici mon appel MySQL:Bash Script Loop Through MySQL

mysql -X -u $MyUSER -p$MyPASS -h$MyHOST -D$MyDB -e'SELECT `theme_name`, `guid` FROM `themes` WHERE `theme_purchased`="1" AND `theme_compiled`='0';' > themes.xml 
download_themes.sh 

Elle exporte les données dans un fichier xml appelé theme.xml en ce moment, je voulais juste trouver un moyen de boucle à travers les données. J'essaie d'éviter PHP et perl et j'essaye juste d'utiliser bash. Merci d'avance.

+4

Y a-t-il une raison spécifique pour laquelle vous voulez éviter les langages de script? Vous ne serez pas capable d'analyser xml correctement dans bash. Vous pourriez même avoir des problèmes en échappant à la sortie. Pourquoi ne pas aller le plus facilement possible et utiliser php/perl/python/lua/java/tcl/javascript/... ou sérieusement quoi que ce soit en dehors de bash qui ne sera tout simplement pas capable de le faire correctement pour de nombreuses sorties? – viraptor

+0

Vous ne savez pas s'il existe un moyen de produire un tableau et de le parcourir en boucle? J'ai googlé cela, je ne pouvais rien trouver. –

Répondre

33

quelque chose comme:

mysql -e "SELECT `theme_name`, `guid` FROM `themes` WHERE `theme_purchased`='1' AND `theme_compiled`='0'" | while read theme_name guid; do 
    # use $theme_name and $guid variables 
    echo "theme: $theme_name, guid: $guid" 
done 

en bref: l'enregistrement des sorties de commande mysql séparés par « \ n » et champs séparés par « \ t » lorsque la sortie est une conduite. la commande read lit une ligne, se sépare en champs et place chacun sur une variable.

si vos données a des espaces dans les champs, vous obtenez quelques problèmes avec la division par défaut read. il y a des moyens de contourner cela; mais si vous lisez seulement deux champs et l'un d'entre eux ne devrait pas avoir d'espaces (comme le guid), alors vous pouvez mettre le champ « dangereux » à la fin, et read mettrez tout « extra » dans la dernière variable .

comme ceci:

mysql -e "SELECT `guid` `theme_name`, FROM `themes` WHERE `theme_purchased`='1' AND `theme_compiled`='0'" | while read guid theme_name; do 
    # use $theme_name and $guid variables 
    echo "theme: $theme_name, guid: $guid" 
done 
+0

Il semblait avoir fonctionné la première fois, mais maintenant il me donne ceci: /winterboard_theme_builder/get_themes.sh: ligne 9: erreur de syntaxe près du jeton inattendu 'done ' /winterboard_theme_builder/get_themes.sh: ligne 9: 'done ' –

+0

En fait, le faire était sur la mauvaise ligne, mais ensuite je reçois une erreur différente. Il est dit /winterboard_theme_builder/get_themes.sh: ligne 7: read: 'theme_name, ': pas un identifiant valide –

+0

oh, c'est vrai. aucune virgule entre les arguments 'read' et un point-virgule avant' do'. fixe – Javier

2

Au lieu de sortie XML, je suggère que vous utilisez simplement la syntaxe SELECT INTO OUTFILE ou mysql --batch --raw à des valeurs séparées par des tabulations sortie. Vous avez alors un accès beaucoup plus facile via bash au reste de la chaîne d'outils Unix, comme cut et awk pour récupérer les champs dont vous avez besoin et les réutiliser avec Bash. Aucun autre langage de script n'est nécessaire et vous n'avez pas besoin de manipuler XML.

mysql --batch --raw -u $MyUSER -p$MyPASS -h$MyHOST -D$MyDB -e'SELECT `theme_name`, `guid` FROM `themes` WHERE `theme_purchased`="1" AND `theme_compiled`='0';' \ 
| awk '{print "theme: " $1 " guid: " $2}' 
3

La réponse acceptée ne fonctionne pas lorsque des espaces sont dans la sortie. Il est une solution facile (IFS = $ \ 't' - Notez le $ - il est bizarre):


>mysql ... -BNr -e "SELECT 'funny man', 'wonderful' UNION SELECT 'no_space', 'I love spaces';" | while IFS=$'\t' read theme_name guid; do echo "theme: $theme_name guid: $guid"; done 
theme: funny man guid: wonderful 
theme: no_space guid: I love spaces 

Vous, bien sûr, veulent remplacer votre propre requête.

1

pipe '|' à while est dangereux, car les changements à l'intérieur de la boucle se produisent dans un autre sous-processus et ne prendraient pas effet dans le script en cours.

D'ailleurs, je déteste de se tourner vers la solution de fichier externe.

Je suggère d'utiliser "Process Substitute".

while read field1 field2 field3 
do 
done < <(mysql -NB -e "$sql") 
# ^
# space needed 
+0

comment détecter si la requête/connexion mysql échoue, dans ce cas? – Siva