Escape doppelte Anführungszeichen im Parameter

109

Unter Unix konnte ich laufen myscript '"test"'und ich würde bekommen "test".

In Windows cmdbekomme ich 'test'.

Wie kann ich doppelte Anführungszeichen als Parameter übergeben? Ich möchte wissen, wie dies manuell aus einem cmdFenster heraus gemacht wird, damit ich kein Programm schreiben muss, um mein Programm zu testen.

Bryan Field
quelle
2
Es ist Jahre her, seit ich eine Windows-Maschine berührt habe, aber funktioniert das Standard-Escape-Zeichen (Backslash \) nicht? zBmyscript \"test\"
Gazler
Nee. Ich bekomme \ test \. Ich vermute, das liegt daran, dass Windows \ anstelle von / verwendet und Backslash nicht als Escaper verwendet werden kann. Aber ich weiß es nicht wirklich.
Bryan Field
Idk, welche Windows-Version Sie verwenden, aber "funktioniert gut unter Windows 7 (Ultimate). Es gibt jedoch eine andere Möglichkeit, mit mehreren Anführungszeichen umzugehen (dh" "wird" oder so), aber ich kann nicht
Finden
2
Mögliches Duplikat von Escaping Double Quotes in Batch Script
Sirdank

Antworten:

22

Ich kann die Symptome nicht schnell reproduzieren: Wenn ich es myscript '"test"'mit einer Batch-Datei versuche, myscript.batdie nur @echo.%1oder sogar enthält @echo.%~1, erhalte ich alle Angebote:'"test"'

Vielleicht können Sie den Fluchtcharakter so ausprobieren ^: myscript '^"test^"'?

mousio
quelle
3
Dann könnten Ihnen die Antworten auf diese Frage vielleicht weiterhelfen?
Maus
2
Ha! Ich hätte nie gedacht, dass es wscriptdie Schuld ist! Überlassen Sie es Windows :)
Bryan Field
4
Eigentlich hat ^ bei mir nicht funktioniert, aber laut
kalenjordan
26
Windows: Das Betriebssystem, in dem Globbing, Shell-Erweiterung und Parameter-Unescaping ausgeführt werden, indem die ausführbare Datei anstelle der Shell aufgerufen wird. Sie wissen nie, welche Konvention, falls vorhanden, die aufgerufenen ausführbaren Ehrungen.
Binki
7
Wertvolle Beiträge: blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/… . Das Caret ist in der Tat der Fluchtcharakter der Wahl für cmd.
Peter - Stellen Sie Monica
198

Eine andere Möglichkeit, Anführungszeichen zu umgehen (obwohl dies wahrscheinlich nicht vorzuziehen ist), die ich an bestimmten Stellen verwendet habe, besteht darin , mehrere doppelte Anführungszeichen zu verwenden . Um den Code anderer Leute lesbar zu machen, werde ich erklären.

Hier sind einige Grundregeln:

  1. Wenn er nicht in doppelten Anführungszeichen Gruppen eingewickelt, Leerzeichen getrennte Parameter:
    program param1 param2 param 3wird auf vier Parameter übergeben program.exe:
         param1, param2, param, und 3.
  2. Eine doppelte Anführungszeichen Gruppe ignoriert Leerzeichen als Wert Separatoren , wenn Parameter Programme übergeben:
    program one two "three and more"werden drei Parameter übergeben program.exe:
         one, two, und three and more.
  3. Um nun einige der Verwirrung zu erklären:
  4. Gruppen in doppelten Anführungszeichen, die direkt neben Text stehen, der nicht in doppelte Anführungszeichen eingeschlossen ist, werden zu einem Parameter zusammengefasst:
    hello"to the entire"worldfungiert als ein Parameter : helloto the entireworld.
  5. Hinweis: Die vorherige Regel impliziert NICHT, dass zwei Gruppen mit doppelten Anführungszeichen direkt nebeneinander angezeigt werden können.
  6. Jedes doppelte Anführungszeichen direkt nach einem abschließenden Anführungszeichen wird als (oder als Teil von) einfachem, nicht umwickeltem Text behandelt, der an die Gruppe mit doppeltem Anführungszeichen angrenzt, aber nur ein doppeltes Anführungszeichen:
    "Tim says, ""Hi!"""fungiert als ein Parameter:Tim says, "Hi!"

Daher gibt es drei verschiedene Arten von doppelten Anführungszeichen: Anführungszeichen, die geöffnet werden, Anführungszeichen, die geschlossen werden, und Anführungszeichen, die als Klartext fungieren.
Hier ist die Aufschlüsselung dieser letzten verwirrenden Zeile:

"Doppelte Anführungszeichengruppe öffnen
T innen "" s
ich in "" s
m innerhalb "" s
    innerhalb "" s - Raum trennt sich nicht
s innerhalb "" s
a inside "" s
y innerhalb "" s
s innerhalb "" s
, innerhalb "" s
    innerhalb "" s - Raum trennt sich nicht
"Gruppe mit doppelten Anführungszeichen schließen
"Zitat folgt direkt näher - fungiert als einfacher unverpackter Text:"
H außerhalb "" s - wird mit der vorherigen benachbarten Gruppe verbunden
ich außerhalb "" s - ...
! außerhalb "" s - ...
"Doppelte Anführungszeichengruppe öffnen
"Doppelte Anführungszeichengruppe schließen
"Zitat folgt direkt näher - fungiert als einfacher unverpackter Text:"

Somit verbindet der Text effektiv vier Gruppen von Zeichen (eine mit nichts jedoch):
Tim says,  ist die erste, umbrochen, um den Leerzeichen zu entkommen,
"Hi!ist die zweite, nicht umbrochen (es gibt keine Leerzeichen)
 ist die dritte, eine Gruppe in doppelten Anführungszeichen, die nichts umschließt
"ist das vierte, das ausgepackte enge Zitat.

Wie Sie sehen können, ist die Gruppe mit doppelten Anführungszeichen immer noch nicht erforderlich, da ohne sie das folgende doppelte Anführungszeichen eine Gruppe mit doppelten Anführungszeichen öffnen würde, anstatt als Klartext zu fungieren.

Daraus sollte ersichtlich sein, dass daher innerhalb und außerhalb von Anführungszeichen drei doppelte Anführungszeichen als nicht entflohenes einfaches Anführungszeichen im Klartext fungieren:

"Tim sagte zu ihm:" Was ist in letzter Zeit passiert? "

wird Tim said to him, "What's been happening lately?"wie erwartet gedruckt . Daher können drei Anführungszeichen immer zuverlässig als Flucht verwendet werden.
Wenn Sie es jedoch verstehen, können Sie feststellen, dass die vier Anführungszeichen am Ende auf nur zwei reduziert werden können, da technisch eine weitere unnötige leere Gruppe mit doppelten Anführungszeichen hinzugefügt wird.

Hier sind einige Beispiele, um es abzuschließen:

Programm ab REM sendet (a) und (b)
Programm "" "a" "" REM sendet ("a")
Programm "" a b "" "REM sendet (" a) und (b ")
Programm "" "" Hallo "" ", sagte Mike." REM sendet ("Hallo", sagte Mike.)
Programm "" a "" b "" c "" d "" REM sendet (abcd), da die "" Gruppen nichts umschließen
Programm "Hallo zu" "" Anführungszeichen "" REM sendet (Hallo zu "Anführungszeichen")
Programm "" "" Hallo Welt "" REM sendet ("Hallo Welt")
Programm "" "Hallo" Welt "" REM sendet ("Hallo Welt")
Programm "" "Hallo" Welt "" REM sendet ("Hallo) und (Welt")
Programm "Hallo" "Welt" "" REM sendet (Hallo "Welt")
Programm "Hallo" "" Welt "" REM sendet (Hallo "Welt")

Schlussbemerkung: Ich habe nichts davon aus einem Tutorial gelesen - ich habe alles durch Experimentieren gefunden. Daher kann meine Erklärung intern nicht zutreffen. Nichtsdestotrotz werden alle obigen Beispiele als gegeben bewertet, wodurch meine Theorie bestätigt (aber nicht bewiesen) wird.

Ich habe dies unter Windows 7, 64-Bit mit nur * .exe-Aufrufen mit Parameterübergabe getestet (nicht * .bat, aber ich würde annehmen, dass es genauso funktioniert).

Codesmith
quelle
11
+1, aber beachten Sie, dass dieses Verhalten von der Anwendung abhängt. In Windows analysiert jede Anwendung ihre eigenen Befehlszeilenparameter. Ich glaube, das Verhalten, das Sie beschreiben, ist das der Standard-C-Bibliothek von Microsoft, die meiner Meinung nach auch von den meisten anderen Windows C-Compilern dupliziert wird.
Harry Johnston
3
Mehrere Fehler in Ihrem letzten Experiment. Programm "" "ab" "" -> ("ab"), Programm "Hallo zu" "" Anführungszeichen "" -> (Hallo zu "Anführungszeichen), Programm" "" "Hallo Welt" "-> (" Hallo) (Welt), Programm "" Hallo "Welt" "-> (" Hallo) (Welt), Programm "" Hallo "Welt" -> ("Hallo Welt), Programm" Hallo "" "Welt" "- > (Hallo "Welt)
Thomson
46
... Ich kann nur sagen, dass Windows-Batchdateien Probleme haben. Dies entgeht Zitaten , um Christi willen; Es sollte keine Raketenwissenschaft sein.
James Ko
4
@ JamesKo Ich könnte nicht mehr zustimmen. Die arkane Absurdität und Inkonsistenz der Windows-Befehlszeile ärgert mich immer wieder. Wer hat diesen Müll entworfen? Oh, die Stunden, die im Laufe der Jahre verschwendet wurden! Unix ist so einfach und macht im Vergleich so viel Sinn.
Carlos A. Ibarra
24

Versuche dies:

myscript """test"""

"" Escape to a Single "im Parameter.

smwikipedia
quelle
1
Das ist nicht ganz richtig. Versuchen Sie es myscript """test test"""und es funktioniert nicht (der erste Parameter wird als übergeben "test. Eigentlich benötigen Sie drei Anführungszeichen: myscript """"test test""Das dritte Anführungszeichen am Ende kann jedoch übersprungen werden.
Ignitor
Was ist, wenn ich alle Anführungszeichen hier entfernen und den Parameterwert in eine Zeichenfolge einfügen muss, die in einem Auswahlabfragefilter verwendet wird? Kann jemand helfen?
SFDC_Learner
2
Vielleicht nicht genau auf diese Frage zugeschnitten, aber das hat mir geholfen, als ich char **argvmit Funktionen wie spawnoder von meinem C-Launcher zu einem anderen Prozess wechseln musste exec. Danke dir. :-)
Jungfrau47
2

Das zweite Dokument, das Peter Mortensen in seinem Kommentar zur Antwort von Codesmith zitierte, machte die Dinge für mich viel klarer. Dieses Dokument wurde von windowsinspired.com geschrieben. Der Link wiederholte sich: Ein besserer Weg, um das Zitieren und Escaping von Windows-Befehlszeilenargumenten zu verstehen .

Einige weitere Versuche und Irrtümer führen zu der folgenden Richtlinie:

Entkomme jedem doppelten Zitat "mit einem Caret ^. Wenn Sie andere Zeichen mit besonderer Bedeutung für die Windows - Befehlsshell wollen (zB <, >, |, &) als reguläre Zeichen stattdessen interpretiert wird, dann sie mit einem caret zu entkommen, auch.

Wenn Sie möchten, dass Ihr Programm foo den Befehlszeilentext empfängt "a\"b c" > dund seine Ausgabe in die Datei out.txt umleitet , starten Sie Ihr Programm wie folgt über die Windows-Befehlsshell:

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

Wenn foo\" als wörtliches doppeltes Anführungszeichen interpretiert und erwartet, dass nicht umschlossene doppelte Anführungszeichen Argumente begrenzen, die Leerzeichen enthalten, interpretiert foo den Befehl so, dass ein Argument a"b c, ein Argument >und ein Argument angegeben werden d.

Wenn foo stattdessen ein doppeltes Anführungszeichen ""als wörtliches doppeltes Anführungszeichen interpretiert , starten Sie Ihr Programm als

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

Die wichtigste Erkenntnis aus dem zitierten Dokument ist, dass für die Windows-Befehlsshell ein nicht entkoppeltes doppeltes Anführungszeichen den Wechsel zwischen zwei möglichen Zuständen auslöst.

Einige weitere Versuche und Irrtümer implizieren, dass im Ausgangszustand die Umleitung (zu einer Datei oder Pipe) erkannt wird und ein Caret ^einem doppelten Anführungszeichen entgeht und das Caret aus der Eingabe entfernt wird. Im anderen Zustand wird die Umleitung nicht erkannt und ein Caret entgeht keinem doppelten Anführungszeichen und wird nicht entfernt. Nennen wir diese Zustände "außen" bzw. "innen".

Wenn Sie die Ausgabe Ihres Befehls umleiten möchten, muss sich die Befehlsshell im Außenzustand befinden, wenn sie die Umleitung erreicht. Daher muss vor der Umleitung eine gerade Anzahl von doppelten Anführungszeichen (durch Caret) stehen. foo "a\"b " > out.txtfunktioniert nicht - die Befehlsshell übergibt das gesamte als kombinierte Befehlszeilenargumente "a\"b " > out.txtan foo , anstatt nur zu übergeben "a\"b "und die Ausgabe an out.txt umzuleiten .

foo "a\^"b " > out.txtfunktioniert auch nicht, da das Caret ^im inneren Zustand angetroffen wird, in dem es sich um ein gewöhnliches Zeichen und nicht um ein Fluchtzeichen handelt, und daher "a\^"b " > out.txtan foo übergeben wird .

Die einzige Möglichkeit, die (hoffentlich) immer funktioniert, besteht darin, die Befehlsshell immer im externen Zustand zu halten, da dann die Umleitung funktioniert.

Wenn Sie keine Umleitung benötigen (oder andere Zeichen mit besonderer Bedeutung für die Befehlsshell), können Sie auf die Carets verzichten. Wenn foo\" als wörtliches doppeltes Anführungszeichen interpretiert wird , können Sie es als bezeichnen

foo "a\"b c"

Dann empfängt foo"a\"b c" als kombiniertes Argument Text und kann ihn als einzelnes Argument gleich interpretieren a"b c.

Nun - endlich - zur ursprünglichen Frage. Wirdmyscript '"test"' von der Windows-Befehlsshell aufgerufen und'"test"' an MyScript übergeben . Anscheinend interpretiert Myscript die einfachen und doppelten Anführungszeichen als Argumenttrennzeichen und entfernt sie. Sie müssen herausfinden, was Myscript als wörtliches Anführungszeichen akzeptiert, und dies dann in Ihrem Befehl angeben, ^um alle Zeichen zu umgehen , die für die Windows-Befehlsshell eine besondere Bedeutung haben. Da dies myscriptauch unter Unix verfügbar ist, reicht es vielleicht aus \". Versuchen

myscript \^"test\^"

oder, wenn Sie keine Umleitung benötigen,

myscript \"test\"
Louis Strous
quelle
DANKE! Ich habe meinen Kopf an die Wand geschlagen und versucht, ein vbscript mit cmd-Eingabeaufforderungstext auszuführen, der in cmd-Eingabeaufforderungstext wiedergegeben wird - das habe ich geerbt - und konnte keinen Weg finden, den Anführungszeichen zu entkommen.
PopeDarren
0

Ich rufe Powershell von cmd aus an, und das Übergeben von Zitaten und keine Flucht hier hat funktioniert. Der schwerwiegende Akzent verhinderte doppelte Anführungszeichen bei diesem Win 10 Surface Pro.

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

Unten sind die Ausgaben aufgeführt, die ich für andere Zeichen erhalten habe, um einem doppelten Anführungszeichen zu entgehen:

la\
la^
la
la~

Die Verwendung eines anderen Zitats, um einem Zitat zu entkommen, führte zu keinen Zitaten. Wie Sie sehen können, wurden die Zeichen selbst getippt, konnten sich aber den doppelten Anführungszeichen nicht entziehen.

Zimba
quelle