2016-05-09 1 views
0

Je fais des scripts pour mes machines virtuelles et j'utilise cygwin. J'ai besoin de définir le nom de l'ordinateur et l'adresse IP. Cette partie est facile, dans cet ordre:Bash appelant programme Windows, comment fonctionne le devis?

wmic computersystem where caption=name "vm-01" 
netsh interface ip set address "Local Area Connection 2" static 10.155.155.50 255.255.255.0 

Cela fonctionne très bien dans cmd.exe. Maintenant, je veux l'exécuter depuis bash. Je veux voir commande J'exécution, donc je suis en utilisant cette fonction bash pour le faire:

call() { 
    echo "[email protected]" 
    [email protected] 
} 

Je l'ai essayé de manière intuitive des citations qui s'échappent:

$ call wmic computersystem where caption=name \"wm-01\" 
Executing (\\BOH\ROOT\CIMV2:Win32_ComputerSystem.Name="XXX")->rename() 
Method execution successful. 
Out Parameters: 
instance of __PARAMETERS 
{ 
     ReturnValue = 87; 
}; 

Ce qui ne marche pas le travail (ne pas être encrassé par « Méthode d'exécution réussie » comme je l'étais au début), le code d'erreur 87.

$ call netsh interface ip set address \"Local Area Connection 2\" static 10.155.155.50 255.255.255.0 

d'autre part, cela fonctionne très bien.

j'ai réussi à le résoudre pour la commande wmic en utilisant

$ call wmic computersystem where caption=name \'wm-01\' 
Executing (\\BOH\ROOT\CIMV2:Win32_ComputerSystem.Name="XXX")->rename() 
Method execution successful. 
Out Parameters: 
instance of __PARAMETERS 
{ 
     ReturnValue = 0; 
}; 

qui fonctionne. J'ai essayé la même chose avec netsh

$ call netsh interface ip set address \'Local Area Connection 2\' static 10.155.155.101 255.255.255.0 
The filename, directory name, or volume label syntax is incorrect. 

qui ne fonctionne pas. Ce que j'essaie de comprendre, c'est pourquoi une commande a besoin de \' et une autre \"?

+0

Dumb question, mais avez-vous essayé avec des citations sans échappement? – Mort

+0

Vous pouvez essayer des guillemets simples autour des guillemets: ''" Local Area Connection 2 "' ', ou guillemets simples seuls:' 'Local Area Connection 2''. – CherryDT

+0

ups, j'ai foiré ma question, j'ai oublié d'inclure la raison pour laquelle je m'échappe. Je le passe en fonction bash qui l'appelle ensuite. S'il vous plaît voir la question mise à jour :) Désolé les gars:/ – Paladin

Répondre

2

Il y a plusieurs choses, il est important de reconnaître ici:

  • la signification de la citation est à la coquille, pas (en général) à la commande en cours de lancement. Le shell supprime les guillemets qui sont importants à cet effet avant d'identifier le nom de la commande et de transférer ses arguments, mais après tous les autres traitements de ligne de commande.

  • Seuls les guillemets non cotés présents dans le texte d'origine d'une commande sont significatifs pour le shell à des fins de citation. En particulier, les caractères de citation résultant de l'expansion des paramètres ne sont pas spéciaux - ils se représentent eux-mêmes.

  • Bien que le shell divise les lignes de commande en jetons avant d'effectuer des extensions, il effectue ensuite une division de mots sur la commande développée. Les expansions qui se produisent dans des devis reconnus sont protégées contre le fractionnement des mots, mais, encore une fois, les citations qui apparaissent de ne sont pas reconnues comme spéciales; ils ne protègent pas contre le partage de mots.

Considérez donc cette version de votre commande:

call netsh interface ip set address "Local Area Connection 2" static 10.155.155.50 255.255.255.0 

bash lit la ligne, il se divise en mots, effectue trivialement extensions, effectue le découpage des mots, et effectue ensuite la suppression des protections, ce qui ces mots:

  • appel
  • netsh
  • Interface
  • ip
  • mis
  • Adresse
  • Connexion locale 2
  • statique
  • 10.155.155.50
  • 255.255.255.0

Notez que « Local Area Connection 2 "(sans les guillemets) est un" mot ". Le premier mot, 'appel', est la commande, et les mots restants sont les arguments, qui sont représentés par [email protected] (ainsi que par $* et les paramètres de position individuels $1, etc.) À l'intérieur de la fonction call(). Maintenant, considérons ce qui se passe quand call() se déplace pour exécuter la commande: il va à peu près comme avant jusqu'à la division des mots, mais là, le nom de la connexion est divisé en plusieurs arguments, et présenté ainsi à la commande netsh .

Je suis sûr que vous avez déjà beaucoup apprécié, mais maintenant considérer cette variation sur votre commande:

call netsh interface ip set address \"Local Area Connection 2\" static 10.155.155.50 255.255.255.0 

Dans ce cas, les " caractères sont échappés, et donc ne servent pas le but de faire la nom de connexion un seul mot shell. Il est donc divisé avant même d'atteindre call(). Vous obtenez donc le même résultat qu'avant, sauf que deux des arguments de netsh comportent des guillemets.

Alors, quelle est la solution? Vous l'avez presque déjà. La différence entre les paramètres spéciaux [email protected] et $* est leur interaction avec la division des mots. Lorsque [email protected] est développé entre guillemets, il est une exception spéciale à la règle que la division de mots n'est pas effectuée sur le résultat - le résultat est divisé entre les éléments de [email protected], mais pas dans eux. Le but principal est exactement le genre de chose que vous essayez de faire: transmettre les paramètres de position du shell à une autre commande.

En d'autres termes, utilisez cette version de votre fonction shell:

call() { 
    echo [email protected] 
    "[email protected]" 
} 

et appelez avec votre ligne de commande d'origine, avec des citations non cotées.

+0

ne savait pas' '" $ @ "', il fait l'affaire et semble fou utile, merci! :) – Paladin