Échapper les guillemets doubles dans le paramètre

109

Sous Unix, je pourrais courir myscript '"test"'et j'obtiendrais "test".

Dans Windows, cmdje reçois 'test'.

Comment puis-je passer des guillemets doubles comme paramètre? J'aimerais savoir comment faire cela manuellement à partir d'une cmdfenêtre pour ne pas avoir à écrire un programme pour tester mon programme.

Champ Bryan
la source
2
Cela fait des années que je n'ai pas touché à une machine Windows, mais le caractère d'échappement standard (barre oblique inverse \) ne fonctionne-t-il pas? par exemplemyscript \"test\"
Gazler
Nan. J'obtiens \ test \. Je soupçonne que c'est parce que Windows utilise \ au lieu de / donc la barre oblique inverse ne peut pas être utilisée comme escaper. Mais je ne sais pas vraiment.
Bryan Field
Identifiez la version de Windows que vous utilisez, mais \ "fonctionne bien sur Windows 7 (Ultimate). Il existe cependant une autre façon de le faire, en traitant plusieurs guillemets (c'est-à-dire" "" devient "ou quelque chose du genre), mais je ne peux pas comprendre quand et comment cela fonctionne.
Codesmith
2
duplication possible de Double Quotes
Échappées dans

Réponses:

22

Je ne peux pas reproduire rapidement les symptômes: si j'essaye myscript '"test"'avec un fichier batch myscript.batcontenant juste @echo.%1ou même @echo.%~1, j'obtiens tous les guillemets:'"test"'

Peut-être que vous pouvez essayer le caractère d'échappement ^comme ceci myscript '^"test^"':?

mousio
la source
3
Alors peut-être que les réponses à cette question pourraient vous aider davantage?
mousio
2
Ha! Je n'aurais jamais deviné que c'était wscriptla faute! Laissez-le à Windows :)
Bryan Field
4
En fait ^ n'a pas fonctionné pour moi, mais \ a fait, selon cette réponse: stackoverflow.com/questions/2403647
...
26
Windows: le système d'exploitation où le globbing, l'expansion du shell et la désactivation des paramètres sont effectués par l'exécutable appelé au lieu du shell. Vous ne savez jamais quelle convention, le cas échéant, l'exécutable invoqué honore.
binki
7
Précieuse contribution: blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/… . Le caret est en effet le caractère d'évasion de choix pour cmd.
Peter - Réintègre Monica
198

Une autre façon d'échapper aux guillemets (bien que probablement pas préférable), que j'ai trouvé utilisée à certains endroits, consiste à utiliser plusieurs guillemets doubles . Dans le but de rendre le code des autres lisible, je vais vous expliquer.

Voici un ensemble de règles de base:

  1. Lorsqu'ils ne sont pas enveloppés dans des groupes doubles guillemets, espaces séparés paramètres:
    program param1 param2 param 3passeront quatre paramètres program.exe:
         param1, param2, paramet 3.
  2. Un groupe double cité ne tient pas compte des espaces comme des séparateurs de valeur lors du passage des paramètres aux programmes:
    program one two "three and more"passera trois paramètres program.exe:
         one, twoet three and more.
  3. Maintenant, pour expliquer une partie de la confusion:
  4. Groupes guillemets doubles qui apparaissent directement adjacents au texte non enveloppé avec des guillemets doubles en se joindre à un paramètre:
    hello"to the entire"worldagit comme un paramètre: helloto the entireworld.
  5. Remarque: la règle précédente n'implique PAS que deux groupes entre guillemets doubles peuvent apparaître directement adjacents l'un à l'autre.
  6. Tout guillemet double directement après un guillemet fermant est traité comme (ou faisant partie d'un) texte brut non emballé adjacent au groupe entre guillemets doubles, mais un seul guillemet double:
    "Tim says, ""Hi!"""agira comme un paramètre:Tim says, "Hi!"

Il existe donc trois types différents de guillemets doubles: les guillemets qui s'ouvrent, les guillemets qui se ferment et les guillemets qui agissent comme du texte brut.
Voici la ventilation de cette dernière ligne déroutante:

"groupe ouvert de guillemets doubles
T à l'intérieur de "" s
je dans "" s
m dans "" s
    à l'intérieur de "" s - l'espace ne se sépare pas
s à l'intérieur de "" s
un intérieur "" s
y à l'intérieur de "" s
s à l'intérieur de "" s
, à l'intérieur de "" s
    à l'intérieur de "" s - l'espace ne se sépare pas
"fermer le groupe avec guillemets doubles
"la citation suit directement de plus près - agit comme un texte non emballé:"
H en dehors de "" s - rejoint le groupe adjacent précédent
je dehors "" s - ...
! dehors "" s - ...
"groupe ouvert de guillemets doubles
"fermer le groupe de guillemets doubles
"la citation suit directement de plus près - agit comme un texte non emballé:"

Ainsi, le texte joint effectivement quatre groupes de caractères (un avec rien, cependant):
Tim says,  est le premier, enveloppé pour échapper les espaces
"Hi!est le second, non enveloppé (il n'y a pas d'espaces)
 est le troisième, un groupe de guillemets doubles n'emballant rien
"est le quatrième, la citation de fermeture déballée.

Comme vous pouvez le voir, le groupe de guillemets doubles n'encapsulant rien n'est toujours nécessaire car, sans lui, les guillemets doubles suivants ouvriraient un groupe entre guillemets au lieu d'agir comme du texte brut.

À partir de là, il devrait être reconnaissable que, par conséquent, entre guillemets intérieurs et extérieurs, trois guillemets doubles agissent comme des guillemets doubles non échappés en texte brut:

"Tim lui a dit:" "" Que s'est-il passé ces derniers temps? "" ""

s'imprimera Tim said to him, "What's been happening lately?"comme prévu. Par conséquent, trois guillemets peuvent toujours être utilisés de manière fiable comme échappatoire.
Cependant, en le comprenant, vous pouvez noter que les quatre guillemets à la fin peuvent être réduits à seulement deux car cela ajoute techniquement un autre groupe vide inutile.

Voici quelques exemples pour le clôturer:

programme ab REM envoie (a) et (b)
programme "" "a" "" REM envoie ("a")
programme "" "a b" "" REM envoie ("a) et (b")
programme "" "" Bonjour, "" "Mike a dit." REM envoie ("Bonjour," dit Mike.)
programme "" a "" b "" c "" d "" REM envoie (abcd) puisque les groupes "" n'enveloppent rien
programme "bonjour à" "" guillemets "" REM envoie (bonjour à "guillemets")
programme "" "" bonjour le monde "" REM envoie ("bonjour le monde")
programme "" "bonjour" monde "" REM envoie ("bonjour le monde")
programme "" "bonjour" monde "" REM envoie ("bonjour) et (monde")
programme "bonjour" "monde" "" REM envoie (bonjour "monde")
programme "bonjour" "" monde "" REM envoie (bonjour "monde")

Note finale: je n'ai lu rien de tout cela à partir d'un tutoriel - j'ai tout inventé en expérimentant. Par conséquent, mon explication n'est peut-être pas vraie en interne. Néanmoins, tous les exemples ci-dessus sont évalués comme donnés, validant (mais non prouvant) ma théorie.

J'ai testé cela sur Windows 7, 64 bits en utilisant uniquement des appels * .exe avec le passage de paramètres (pas * .bat, mais je suppose que cela fonctionne de la même manière).

Codemith
la source
11
+1, mais notez que ce comportement dépend de l'application. Sous Windows, chaque application analyse ses propres paramètres de ligne de commande. Je pense que le comportement que vous décrivez est celui de la bibliothèque C standard de Microsoft, qui, je pense, est également dupliquée par la plupart des autres compilateurs Windows C.
Harry Johnston
3
Plusieurs erreurs dans votre dernière expérimentation. programme "" "ab" "" -> ("ab"), programme "bonjour à" "" guillemets "" -> (bonjour à "guillemets), programme" "" "bonjour le monde" "-> (" Bonjour) (monde), programme "" "bonjour" monde "" -> ("bonjour) (monde), programme" "" bonjour "monde" "-> (" bonjour le monde), programme "bonjour" "" monde "" - > (bonjour "monde)
Thomson
46
... Tout ce que je peux dire, c'est que les fichiers batch Windows ont des problèmes. Ce sont des citations qui échappent , pour l'amour du Christ; cela ne devrait pas être une sorte de science-fusée.
James Ko
4
@JamesKo Je ne pourrais pas être plus d'accord. L'absurdité et l'incohérence obscures de la ligne de commande Windows ne manquent jamais de me mettre en colère. Qui a conçu cette jonque? Oh, les heures perdues au fil des ans! Unix est si simple et a tellement de sens en comparaison.
Carlos A. Ibarra
24

Essaye ça:

myscript """test"""

"" échapper à un seul "dans le paramètre.

smwikipedia
la source
1
Ce n'est pas tout à fait correct. Essayez myscript """test test"""et cela ne fonctionne pas (le premier paramètre est transmis comme "test. En réalité, vous avez besoin de trois guillemets: myscript """"test test""le troisième guillemet à la fin peut être ignoré, cependant.
Ignitor
Que faire si je dois supprimer tous les guillemets ici et placer la valeur du paramètre dans une chaîne utilisée dans un filtre de requête de sélection? Quelqu'un peut-il aider?
SFDC_Learner
2
Peut-être pas exactement pour cette question, mais cela m'a aidé lorsque je devais passer char **argvde mon lanceur C à un autre processus en utilisant des fonctions comme spawnou exec. Je vous remercie. :-)
virgo47
2

Le 2ème document cité par Peter Mortensen dans son commentaire sur la réponse de Codesmith a rendu les choses beaucoup plus claires pour moi. Ce document a été écrit par windowsinspired.com. Le lien répété: Un meilleur moyen de comprendre la citation et l'échappement des arguments de ligne de commande Windows .

Quelques essais et erreurs supplémentaires conduisent à la directive suivante:

Échappez à chaque double guillemet "avec un signe d'insertion ^. Si vous voulez d' autres caractères avec une signification particulière pour l'interpréteur de commandes de Windows (par exemple <, >, |, &) doivent être interprétés comme des caractères réguliers au lieu, puis les échapper avec un accent circonflexe, aussi.

Si vous voulez que votre programme foo reçoive le texte de la ligne de commande "a\"b c" > det redirige sa sortie vers le fichier out.txt , démarrez votre programme comme suit à partir du shell de commande Windows:

foo ^"a\^"b c^" ^> d > out.txt

Si foo interprète \"comme un guillemet double littéral et s'attend à ce que des guillemets doubles non échappés délimitent les arguments qui incluent des espaces, alors foo interprète la commande comme spécifiant un argument a"b c, un argument >et un argument d.

Si à la place foo interprète un guillemet double ""comme un guillemet double littéral, alors démarrez votre programme comme

foo ^"a^"^"b c^" ^> d > out.txt

Le point clé du document cité est que, pour le shell de commande Windows, un guillemet double non échappé déclenche le basculement entre deux états possibles.

Quelques essais et erreurs supplémentaires impliquent que dans l'état initial, la redirection (vers un fichier ou un tube) est reconnue et un curseur ^échappe à un guillemet double et le curseur est supprimé de l'entrée. Dans l'autre état, la redirection n'est pas reconnue et un signe d'insertion n'échappe pas à un guillemet double et n'est pas supprimé. Faisons référence à ces états comme «extérieur» et «intérieur», respectivement.

Si vous souhaitez rediriger la sortie de votre commande, alors le shell de commande doit être dans l'état extérieur lorsqu'il atteint la redirection, il doit donc y avoir un nombre pair de guillemets doubles non échappés (par un caret) précédant la redirection. foo "a\"b " > out.txtne fonctionnera pas - le shell de commande passe le tout "a\"b " > out.txtà foo en tant qu'arguments de ligne de commande combinés, au lieu de passer uniquement "a\"b "et de rediriger la sortie vers out.txt .

foo "a\^"b " > out.txtne fonctionnera pas non plus, car le signe d'insertion ^est rencontré dans l'état intérieur où il s'agit d'un caractère ordinaire et non d'un caractère d'échappement, il "a\^"b " > out.txtest donc passé à foo .

La seule façon qui (espérons-le) fonctionne toujours est de garder le shell de commande toujours dans l'état extérieur, car alors la redirection fonctionne.

Si vous n'avez pas besoin de redirection (ou d'autres caractères ayant une signification particulière pour le shell de commande), vous pouvez vous passer des caractères carats. Si foo est interprété \"comme un guillemet double littéral, vous pouvez l'appeler comme

foo "a\"b c"

Ensuite, foo reçoit "a\"b c"comme argument combiné le texte et peut l'interpréter comme un argument unique égal à a"b c.

Maintenant - enfin - à la question initiale. myscript '"test"'appelé à partir du shell de commande Windows passe '"test"'à myscript . Apparemment, myscript interprète les guillemets simples et doubles comme des délimiteurs d'argument et les supprime. Vous devez déterminer ce que myscript accepte comme guillemet double littéral, puis le spécifier dans votre commande, en utilisant ^pour échapper tous les caractères qui ont une signification particulière pour le shell de commande Windows. Étant donné que cela myscriptest également disponible sur Unix, peut \"- être fait - il l'affaire. Essayer

myscript \^"test\^"

ou, si vous n'avez pas besoin de redirection,

myscript \"test\"
Louis Strous
la source
MERCI! Je me cognais la tête contre le mur en essayant d'exécuter un vbscript avec le texte d'invite cmd renvoyé dans le texte d'invite cmd - j'ai hérité de cela - et je n'ai pas pu trouver un moyen d'échapper aux guillemets.
PopeDarren
0

J'appelle PowerShell à partir de cmd, et en passant des guillemets et aucun des deux échappements ici n'a fonctionné. L'accent grave a travaillé pour échapper aux guillemets doubles sur ce pro de surface Win 10.

>powershell.exe "echo la`"" >> test
>type test
la"

Voici les sorties que j'ai obtenues pour que d'autres personnages échappent à un guillemet double:

la\
la^
la
la~

L'utilisation d'une autre citation pour échapper à une citation n'a entraîné aucune citation. Comme vous pouvez le voir, les caractères eux-mêmes ont été tapés, mais n'ont pas échappé aux guillemets.

Zimba
la source