2016-06-16 6 views
9

Ich habe diesen einfachen Test Skript bekam:Warum werden zur Laufzeit Leerzeichen in diese Batch-Datei eingefügt?

echo start 
falsey^
&& echo nope 
echo end 

falsey ist ein kleines C-Programm I-Test zu helfen gemacht, gibt es einfach 1:

int main(int argc, const char** argv) { 
     return 1; 
} 

Das Problem ist, wenn ich öffnen cmd und diese Batch-Skript ausführen, es fügt ein paar Räume zwischen den beiden & s, die es verursacht natürlich falsch nope echo zu:

C:\jenkins-foo-test>foo.bat 
C:\jenkins-foo-test>echo start 
start 
C:\jenkins-foo-test>falsey & & echo nope 
nope 
C:\jenkins-foo-test>echo end 
end 

Ich habe ein paar Abhilfen für diese herausgefunden, wie setzt Anführungszeichen um den &&:

falsey^
"&&" echo nope 

Zitate tatsächlich in diesem Fall nicht funktionieren, siehe @dbenham's answer warum.

die ^ dropping und Zusammenführen der beiden Leitungen:

falsey && echo nope 

oder einen Raum vor dem && Zugabe:

falsey^
&& echo nope 

Jede dieser drei Optionen nicht korrekt gedruckt nope do. Aber alle haben noch zusätzliche Leerzeichen, wenn cmd.exe die Befehle ausgibt, die es ausführt.

Warum werden diese zusätzlichen Leerzeichen eingefügt und wie kann ich verhindern, dass cmd.exe Dinge zerlegt, ohne meinen Code ständig in leicht unnatürliche Formen zu bringen?

+2

Was hat den Vorteil, einen Zeilenumbruch zu vermeiden und '&&' trotzdem in die nächste Zeile zu setzen? 'false && echo nope' oder' falsey && (\ n echo nope \ n) '(wobei' \ n' neue Zeilen sind) ist Standardkonvention. Was Sie tun, fühlt sich an, als würde man einen Satz mit einer Konjunktion beginnen. Und es ist peinlich. – rojo

+0

Mit welchem ​​Texteditor bearbeiten Sie Ihre Batch-Datei? –

+0

@rojo Weil die Zeilen, für die ich das verwenden möchte, ziemlich lang sind. Das Setzen von '&&' am Anfang der nächsten Zeile macht deutlich, dass die Ausführung von der vorherigen Zeile abhängt. – 8bittree

Antwort

8

The line continuation ^ escapes the first character on the next line, so wird die erste & als Literal behandelt und als Argument an falsey übergeben. Die zweite & wird als einfache Befehlsverkettung behandelt.

Eine einfache Lösung zu erhalten && als bedingte Befehl Verkettung behandelt werden soll, die && auf der Linie setzen, bevor:

falsey &&^ 
echo nope 

oder Sie ein Leerzeichen vor dem &&

falsey^
&& echo nope 

setzen könnte Die andere Möglichkeit besteht darin, den Umleitungstrick zu verwenden, den jeb in seiner verknüpften Antwort angibt, aber ich benutze diesen Trick nie.


In Bezug auf Ihre "Lösung" mit "&&" zitiert - Sie selbst zum Narren halten. Es scheint zu funktionieren, wenn eine Fehlfunktion fehlschlägt.Aber wenn Ihr Befehl erfolgreich ist, dann haben Sie Probleme:

echo ONE^
"&&" echo TWO 

- OUTPUT -

C:\test>echo ONE " && " echo TWO 
ONE " 
'" echo TWO' is not recognized as an internal or external command, 
operable program or batch file. 

Beachten Sie, dass die && funktioniert, weil die ersten " ist entkommen, so die && nicht zitiert. Wenn Sie ein Leerzeichen vor dem

"&&" hinzufügen
echo ONE^ 
"&&" echo TWO 

dann erhalten Sie die folgende

C:\test>echo ONE "&&" echo TWO 
ONE "&&" echo TWO 

weil jetzt der Raum entkommen ist und die "&&" zitiert wird.


Ihren Kommentar In Bezug auf, können Sie diese zusätzlichen Leerzeichen ignorieren - sie sind ein Artefakt, wie der Parser zeigt die Linie, wenn ECHO ON ist. Der Parser ordnet die Zeile oft signifikant neu an, aber normalerweise beeinflusst dies das Ergebnis nicht.

Zum Beispiel

< nul set test=OK 
echo [%test%] 

--OUTPUT--

C:\test>set test=OK 0<nul 

C:\test>echo [OK] 
[OK] 

Hinweis, wie die Echo-SET Linie vollständig neu geordnet wird. Die Umleitung wird komprimiert und an das Ende der Anweisung mit einem Leerzeichen vor der Umleitung verschoben. Sie könnten denken, dass der Raum in der Zuweisung enthalten wäre, aber Sie können sehen, dass es nicht ist :-)

Die einzige Zeit, die Sie möglicherweise über die Umordnung sich sorgen müssen, ist, wenn der Befehl in einer Leitung benutzt wird.

Zum Beispiel:

(set test=OK&call echo [%%^^test%%])|findstr "^" 

--OUTPUT--

C:\test>(set test=OK & call echo [%^test%]) | findstr "^" 
[OK ] 

Sie können sehen, dass es ein einziger unerwünschter zusätzlicher Platz ist, die in dem SOLL-Wert enthalten ist. Dies ist ein Artefakt dafür, wie Pipes implementiert werden - jede Seite wird in einem neuen CMD.EXE-Prozess ausgeführt und die Zeile wird mehrfach analysiert. Sie können sehen, wo der Speicherplatz herkommt, indem Sie %CMDCMDLINE% verwenden, um die Befehlszeile anzuzeigen, die an die Cmd.exe der linken Seite übergeben wird.

(set test=OK&call echo [%%^^test%%] %%^^cmdcmdline%%)|findstr "^" 

--OUTPUT--

C:\test>(set test=OK & call echo [%^test%] %^cmdcmdline%) | findstr "^" 
[OK ] C:\WINDOWS\system32\cmd.exe /S /D /c" (set test=OK & call echo [%^test%] %^cmdcmdline%)" 

Why does delayed expansion fail when inside a piped block of code? Sehen Sie für weitere Informationen über viele Macken mit Rohren. Achten Sie insbesondere auf die ausgewählte Antwort, um eine gute Erklärung für das Geschehen zu erhalten.

+0

Was ist mit den zusätzlichen Leerzeichen wenn es kein '^' gibt und alles ist eine Zeile? – 8bittree

+0

@ 8bittree - Diese zusätzlichen Leerzeichen erscheinen nur in der Ausgabe, wenn der Befehl wiederholt wird (ECHO ist EIN). Sie sind ein Artefakt des Parsers. Die Leerzeichen werden nicht an den Befehl übergeben, sodass sie keine Auswirkungen haben. Die einzige Auswirkung haben sie, wenn der Befehl mehrmals geparst und in einem neuen cmd.exe-Prozess ausgeführt wird, z. B. wenn er in einer Pipe verwendet wird. – dbenham

+0

@ 8bittree - Sehen Sie sich meine zuletzt für eine bessere Erklärung für die „extra Räume“, als auch, warum man sich normalerweise ignorieren. – dbenham

Verwandte Themen