Question

Comment pourrais-je aller à remplacer tous les guillemets doubles dans les paramètres de mon fichier de commandes avec des guillemets doubles échappées? Ceci est mon fichier de commandes en cours, qui se développe à l'intérieur de la chaîne tous ses paramètres de ligne de commande:

@echo off
call bash --verbose -c "g++-linux-4.1 %*"

Il utilise ensuite cette chaîne pour faire un appel à bash Cygwin, l'exécution d'un compilateur croisé Linux. Malheureusement, je reçois des paramètres tels que ceux-ci passé à mon fichier batch:

"launch-linux-g++.bat" -ftemplate-depth-128 -O3 -finline-functions 
-Wno-inline -Wall  -DNDEBUG   -c 
-o "C:\Users\Me\Documents\Testing\SparseLib\bin\Win32\LinuxRelease\hello.o" 
"c:\Users\Me\Documents\Testing\SparseLib\SparseLib\hello.cpp"

Lorsque la première citation dans le premier trajet est passé en terminant prématurément la chaîne étant transmis à GCC, et en passant le reste des paramètres directement à bash (qui échoue spectaculairement.)

J'imagine si je peux concaténer les paramètres en une seule chaîne échapper alors les guillemets il devrait fonctionner correctement, mais je vais avoir du mal à déterminer comment faire cela. Est-ce que quelqu'un sait?

Était-ce utile?

La solution 3

Google a fini avec la réponse. La syntaxe de remplacement de chaîne en lots est la suivante:

set v_myvar=replace me
set v_myvar=%v_myvar:ace=icate%

Ce qui produit "me répliquer". Mon script ressemble maintenant à ceci:

@echo off
set v_params=%*
set v_params=%v_params:"=\"%
call bash -c "g++-linux-4.1 %v_params%"

remplace toutes les instances de " avec \", correctement saisies pour bash.

Autres conseils

Le caractère d'échappement dans les scripts de traitement par lots est ^. Mais pour les chaînes entre guillemets doubles, doubler les guillemets:

"string with an embedded "" character"

eplawless propre réponse simple et résout efficacement son problème spécifique: il remplace toutes les instances de " dans la liste des arguments avec toute \" , ce qui est la façon dont Bash nécessite des guillemets doubles, une chaîne double cité à représenter.

Pour répondre de façon générale la question de comment échapper les guillemets doubles, une chaîne double entre guillemets cmd.exe , l'interpréteur de ligne de commande de Windows (que ce soit sur la ligne de commande - souvent encore, à tort appelé " DOS invite » - ou dans un fichier batch): Voir en bas pour un look à PowerShell

.

tl; dr :

  • doit utiliser "" lors du passage d'une chaîne à un (autre) fichier batch vous peut utiliser "" avec les applications créées avec Microsoft 's C / C ++ /. compilateurs NET (qui aussi accepter \"), qui sous Windows comprend Python et Node.js :

    • Exemple: foo.bat "We had 3"" of rain."

    • Concerne les fichiers batch seulement:

      • "" est le seul moyen d'obtenir l'interpréteur de commande (cmd.exe) pour traiter toute la chaîne entre guillemets comme à argument.

      • Malheureusement, cependant, ne sont pas seulement les guillemets doubles entourant répartis (comme d'habitude), mais si on les échappées doublé, pour obtenir ainsi la chaîne de caractères prévue est un processus en deux étapes; par exemple, en supposant que la chaîne double cité est passé comme 1er argument %1:

      • set "str=%~1" supprime les guillemets doubles enserrant; set "str=%str:""="%" convertit ensuite les guillemets doubles à ceux doublé simples.
        Assurez-vous d'utiliser les guillemets doubles enserrant autour des pièces d'affectation afin d'éviter une interprétation non désirée des valeurs.

  • \" est requis - comme la seule option - par de nombreux autres programmes , (Eg, Ruby, Perl, et même propre PowerShell de Microsoft ()) , mais UTILISATION EST DANGEREUX :

    • \" est ce que beaucoup de executables et d'interprètes soit exigent - y compris le propre PowerShell de Microsoft lorsque les chaînes passent de l'extérieur - ou, dans le cas de compilateurs Microsoft, soutien comme une alternative à "" -. en fin de compte, cependant, il est au programme cible pour analyser la liste des arguments
      • Exemple: foo.exe "We had 3\" of rain."
    • CEPENDANT, UTILISATION DE \" PEUT PROVOQUER INDÉSIRABLES, ARBITRAIRE EXECUTION DES ORDRES et / ou Redirections ENTRÉE / SORTIE :
      • Les caractères suivants présentent ce risque: & | < >
      • Par exemple, les résultats suivants dans l'exécution involontaire de la commande ver; voir plus loin pour une explication et le point suivant pour une solution de contournement:
        • foo.exe "3\" of snow" "& ver."
    • Pour PowerShell sur de Windows , \"" et "^"" sont des alternatives robustes, mais limitées (voir la section "Appel CLI PowerShell ..." ci-dessous ).
  • Si vous devez utiliser \", il y a seulement 3 sécurité approches , qui sont cependant assez lourd : Astuce du chapeau TS pour son aide.

    • Utilisation (peut-être sélectif ) a retardé l'expansion variable dans votre fichier de commandes, vous pouvez magasin \" littéral dans une variable et référence variable dans une chaîne de "..." en utilisant la syntaxe !var! - voir T S .

      • L'approche ci-dessus, en dépit d'être lourde, a l'avantage que vous pouvez l'appliquer méthodiquement et que cela fonctionne avec vigueur , avec une entrée.
    • uniquement avec des chaînes littérales - ceux ne comportant PAS VARIABLES - obtenez-vous une approche tout aussi méthodique: catégorique ^-évasion tous cmd.exe métacaractères: " & | < > et - si vous voulez aussi supprimer l'extension de variable - %:
      foo.exe ^"3\^" of snow^" ^"^& ver.^"

    • Dans le cas contraire, vous devez formuler votre chaîne fondée sur la reconnaissance que des parties de la cmd.exe chaîne considère unquoted en raison de mal interpréter \" comme délimiteurs de fermeture:

      • en littéral portions contenant des métacaractères du shell: les ^-fuite; en utilisant l'exemple ci-dessus, il est & qui doit être ^-échappé:
        foo.exe "3\" of snow" "^& ver."

      • dans les parties avec des références variables de style %...% : veiller à ce que cmd.exe les considère comme faisant partie d'une chaîne de "..." et qui que les valeurs des variables ne le font pas eux-mêmes ont intégré , citations asymétriques -. qui est même pas toujours possible

Pour plus d'information, lisez la suite.


Historique

Note: Ceci est basé sur mes propres expériences. Ne laissez-moi savoir si je me trompe.

Shells POSIX comme tels que Bash sur le programme cible systèmes Unix tokenize la liste des arguments (chaîne) avant la transmission d'arguments individuellement : entre autres extensions, ils diviser la liste des arguments en mots individuels (séparation de mots) et supprimer les caractères citant des mots résultant (citation suppression). Le programme cible est remis un array de arguments individuels , avec des guillemets syntaxiques supprimés .

En revanche, l'interpréteur de commandes de Windows ne tokenize apparemment pas la liste des arguments et passe simplement le à chaîne comprenant tous arguments - y compris les caractères citant. -. Au programme cible Cependant, certains pré-traitement a lieu avant la chaîne unique est transmise au programme cible: ^ échapper à caractères. en dehors des chaînes entre guillemets sont enlevés (ils échappent à l'omble chevalier suivant.) et des références variables (par exemple, %USERNAME%) sont interpolée premier.

Ainsi, contrairement à Unix, il est de la responsabilité du programme cible pour analyser pour analyser la chaîne d'arguments et de le décomposer en arguments individuels avec des guillemets supprimés. Ainsi, les programmes différents peuvent nécessiter hypothétiquement différentes méthodes qui s'échappent et il n'y a pas un seul mécanisme d'échappement qui est garantie pour travailler avec tous les programmes - < a href = « https://stackoverflow.com/a/4094897/45375 »> https://stackoverflow.com/a/4094897/45375 contient un excellent fond sur l'anarchie qui est l'analyse syntaxique ligne de commande Windows.

Dans la pratique, \" est très fréquent, mais pas SÛR , comme mentionné ci-dessus:

Depuis cmd.exe lui-même ne reconnaît pas \" comme se sont échappés guillemet, il peut mal interpréter plus tard jetons sur la ligne de commande comme unquoted et potentiellement les interpréter comme commandes et / ou entrée / sortie redirections .
En résumé: les surfaces de problème, si l'un des caractères suivants suivent un ouverture ou asymétrique \": & | < > ; par exemple:

foo.exe "3\" of snow" "& ver."

cmd.exe voit les jetons suivants, résultant de mauvaise interprétation\" comme guillemet régulier:

  • "3\"
  • of
  • snow" "
  • repos: & ver.

Depuis cmd.exe pense que & ver. est non cotées , il l'interprète comme & (l'opérateur commande le séquençage), suivi du nom d'une commande à exécuter (ver. - le . est ignoré, les rapports de ver informations sur la version de cmd.exe).
L'effet global est:

  • Tout d'abord, foo.exe est invoqué avec le premier 3 jetons seulement.
  • Ensuite, la commande est exécutée ver.

Même dans les cas où la commande accidentelle ne fait pas de mal, votre commande globale ne fonctionnera pas comme prévu, étant donné que tous les arguments sont transmis.

De nombreux compilateurs / interprètes ne reconnaissent que \" - par exemple, la GNU C / C ++, Python, Perl, Ruby, même propre PowerShell appelé à partir de Microsoft cmd.exe - et, à l'exception de PowerShell avec \"", pour eux il n'y a pas de solution simple à ce problème. Essentiellement, vous auriez à savoir à l'avance quelles parties de votre ligne de commande sont mal interprétés comme non cotés, et ^-s'échapper de manière sélective toutes les instances de & | < > dans ces parties.

En revanche, utilisation de "" est SÛR , mais est malheureusement pris en charge uniquement par executables base compilateur Microsoft et les fichiers batch (dans le cas des fichiers de traitement par lots, avec les bizarreries ci-dessus), discuté qui exclut notables PowerShell -. voir la section suivante


Appel de CLI de PowerShell à partir de coquilles de cmd.exe ou comme POSIX:

Note: Voir la section inférieure de la façon dont est traitée citant le dans PowerShell

.

PowerShell , lorsqu'il est appelé de l'extérieur - par exemple, de cmd.exe, que ce soit à partir de la ligne de commande ou d'un fichier batch - reconnaît uniquement \" et, sous Windows également """ et \"" plus robuste / "^"" (même si interne PowerShell utilise ` comme le caractère d'échappement dans les chaînes entre guillemets doubles et accepte également "" - voir en bas section):

de Windows , appelant cmd.exe / un fichier batch:

  • "" pauses , car il est fondamentalement non pris en charge:

    • powershell -c " ""ab c"".length " -> erreur "La chaîne est manquante la terminaison"
  • \" et """ travail , en principe, , mais ne sont pas sécurité :

    • powershell -c " \"ab c\".length " fonctionne comme prévu: il émet 5 (note 2 espaces)
    • Mais ce n'est pas sûr, parce que cmd.exe métacaractères briser la commande, à moins que se sont échappés:
      powershell -c " \"a& c\".length " pauses , en raison de la &, qui devrait être échappé comme ^&
  • \"" est sécurité , mais normaliser l'intérieur des espaces , qui peut être non souhaité:

    • sorties powershell -c " \""a& c\"".length " 4 (!), Parce que les 2 espaces sont normalisés à 1.
  • "^"" est le meilleur choix pour Windows PowerShell spécifiquement , où il est à la fois sécuritaire et la préservation des espaces, mais avec PowerShell de base (sous Windows), il est le même que \"" , c.-à-whitespace- normalisant . Le crédit va à Venryx pour découvrir cette approche.

    • powershell -c " "^""a& c"^"".length " fonctionne :. ne pas casser - malgré & - et sorties 5, à savoir, les espaces correctement conservés

    • PowerShell Tore : pwsh -c " "^""a& c"^"".length " fonctionne , mais les sorties 4, ie normalise les espaces , comme \"" fait

      <. / li>

les plates-formes Unix-like (Linux, Mac OS), appelant PowerShell Tore CLI de, pwsh à partir d'une coquille Posix telle comme bash:

doit utiliser \" , qui est cependant à la fois sûr et des espaces préservant :

$ pwsh -c " \"a&  c|\".length" # OK: 5

Informations connexes


Je cite dans les PowerShell:

Windows PowerShell est un shell beaucoup plus avancé que cmd.exe, et il a fait partie de Windows depuis de nombreuses années (et PowerShell de base a l'expérience PowerShell pour MacOS et Linux ainsi).

fonctionne PowerShell toujours interne par rapport à citer:

  • à l'intérieur des chaînes entre guillemets doubles, utilisez `" ou "" pour échapper à des guillemets doubles
  • dans les chaînes entre guillemets simples, utilisez '' pour échapper à guillemets simples

Cela fonctionne sur la ligne de commande PowerShell et passer des paramètres aux scripts PowerShell ou fonctions de dans les PowerShell.

(Comme indiqué plus haut, le passage d'un guillemet échappé à PowerShell de l'extérieur nécessite \" ou, plus robuste, \"" - rien ne fonctionne autrement).

Malheureusement, lors de l'appel externes programmes de PowerShell, vous êtes confrontés à la nécessité à la fois adapter propres règles de cotation de PowerShell et pour échapper à la cible programme:

Ce comportement problématique est également discuté et résumées dans cette GitHub docs question

Double -quotes intérieur doubles chaînes -quoted :

Considérez chaîne "3`" of rain", qui PowerShell interne se traduit par 3" of rain littérale.

Si vous voulez transmettre cette chaîne à un programme externe, vous devez appliquer le programme de cible échapper en plus de PowerShell ; dites que vous voulez passer la chaîne à un programme C, qui s'attend intégré entre guillemets doubles à échapper comme \":

foo.exe "3\`" of rain"

Notez comment à la fois `" - pour faire PowerShell heureux - et la \ - pour que le programme cible heureux - doit être présent.

La même logique vaut pour appeler un fichier batch, où "" doit être utilisé:

foo.bat "3`"`" of rain"

En revanche, l'intégration à -quotes dans à double chaîne entre guillemets aucune fuite du tout.

simple -quotes intérieur à chaînes -quoted faire pas besoin supplémentaire échapper; considérer '2'' of snow', qui est la représentation « de PowerShell 2' of snow.

foo.exe '2'' of snow'
foo.bat '2'' of snow'

PowerShell se traduit par des chaînes entre guillemets simples à les guillemets doubles avant de les transmettre au programme cible.

Cependant, à double -quotes intérieur à chaînes -quoted , qui ne ont pas besoin pour échapper à PowerShell , ne doivent encore être échappé pour le programme cible :

foo.exe '3\" of rain'
foo.bat '3"" of rain'

PowerShell v3 introduit la magie option --% , appelé symbole stop-analyse syntaxique , ce qui atténue quelque peu la douleur, en passant quoi que ce soit après il non interprété au programme cible, sauf pour les références variables d'environnement de style cmd.exe (par exemple, %USERNAME%), qui sont élargi; par exemple:.

foo.exe --% "3\" of rain" -u %USERNAME%

Notez comment échapper à la " intégré comme \" pour le programme cible (et non aussi pour PowerShell comme \`") suffit.

Cependant, cette approche:

  • ne permet pas de échapper caractères % afin d'éviter des extensions variables d'environnement.
  • exclut directement utiliser des variables et des expressions PowerShell; à la place, la ligne de commande doit être construite dans une variable de chaîne dans une première étape, puis appelé avec Invoke-Expression dans une seconde.

Ainsi, en dépit de ses nombreuses avancées, PowerShell n'a pas fait échapper beaucoup plus facile lors de l'appel des programmes externes. cependant, il a introduit un soutien pour les chaînes entre guillemets simples.

Je me demande s'il est fondamentalement possible dans le monde Windows pour passer toujours au modèle Unix de laisser le shell faire tout le retrait de tokens et citation on pouvait s'y attendre , à l'avant , quel que soit le programme cible , puis appeler le programme cible en faisant passer les jetons obtenus.

En complément excellente réponse mklement0:

Presque tous acceptent executables \" comme un " échappé. une utilisation sûre dans cmd est cependant presque possible en utilisant DELAYEDEXPANSION.
Pour envoyer un " littéral explicitement à un processus, à attribuer \" une variable d'environnement, et ensuite utiliser cette variable, chaque fois que vous devez passer un devis. Exemple:

SETLOCAL ENABLEDELAYEDEXPANSION
set q=\"
child "malicious argument!q!&whoami"

Note SETLOCAL ENABLEDELAYEDEXPANSION semble fonctionner que dans des fichiers batch. Pour obtenir DELAYEDEXPANSION dans une session interactive, commencez cmd /V:ON.

Si votre batchfile does't travail avec DELAYEDEXPANSION, vous pouvez l'activer temporairement:

::region without DELAYEDEXPANSION

SETLOCAL ENABLEDELAYEDEXPANSION
::region with DELAYEDEXPANSION
set q=\"
echoarg.exe "ab !q! & echo danger"
ENDLOCAL

::region without DELAYEDEXPANSION

Si vous voulez passer un contenu dynamique à partir d'une variable qui contient des citations qui ont réussi à sortir "" vous pouvez remplacer "" avec \" sur l'expansion:

SETLOCAL ENABLEDELAYEDEXPANSION
foo.exe "danger & bar=region with !dynamic_content:""=\"! & danger"
ENDLOCAL

Ce remplacement n'est pas en sécurité avec l'expansion du style %...%!

En cas de OP bash -c "g++-linux-4.1 !v_params:"=\"!" est la version sûre.


Si pour une raison quelconque permettant même temporairement DELAYEDEXPANSION n'est pas une option, continuez à lire:

Utilisation \" à l'intérieur cmd est un peu plus sûr si on a toujours besoin d'échapper à des caractères spéciaux, au lieu de juste parfois. (Il est moins susceptible d'oublier un caret, si elle est cohérente ...)

Pour ce faire, l'un précède une citation avec un caret (^"), des citations qui devraient atteindre le processus d'enfant littéraux doivent en outre être échappé avec un jeu (\^"). tous shell caractères meta doivent être échappés avec ^ ainsi, par exemple & => ^&; | => ^|; > => ^>; etc.

Exemple:

child ^"malicious argument\^"^&whoami^"

Source: Tout le monde cite les arguments de ligne de commande dans le mauvais sens , voir « Une meilleure méthode de citer »


Pour passer du contenu dynamique, il faut vérifier les points suivants:
La partie de la commande qui contient la variable doit être considérée comme « cité » par cmd.exe (Ceci est impossible si la variable peut contenir des citations - ne pas écrire %var:""=\"% ). Pour ce faire, la dernière " avant la variable et la première " après la variable ne sont pas ^-échappé. cmd-métacaractères entre ces deux " ne doivent pas être échappé. Exemple:

foo.exe ^"danger ^& bar=\"region with %dynamic_content% & danger\"^"

Ce n'est pas sûr, si %dynamic_content% peut contenir des guillemets non.

Par exemple pour le moteur Unreal outil d'automatisation de la gestion fichier batch - cela a fonctionné pour moi

par exemple:  -cmdline = "-Messaging" -device = dispositif -addcmdline = "- sessionId = Session -SessionOwner = 'propriétaire' -SessionName = 'Build' -dataProviderMode = -LogCmds locales = 'LogCommodity OFF' -execcmds liste d'automatisation '; runtests essais séparés + + by + T1 + T2; quitter »" -run

Espérons que cela aide quelqu'un, a travaillé pour moi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top