2016-06-16 1 views
9

が、私はこの単純なテストスクリプトを持っている:実行時にこのバッチファイルにスペースが挿入されるのはなぜですか?

echo start 
falsey^
&& echo nope 
echo end 

falseyは、私がテストを支援するために作られた小さなCプログラムである、それは単に1返します

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

私が開くときに問題がありますcmdを実行してこのバッチスクリプトを実行すると、2つの&の間に2つの空白が挿入され、間違ってエコーが返されます。nope

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 

私は、このような、このためのいくつかの回避策は、&&の前後に引用符を入れて考え出した:

falsey^
"&&" echo nope 

引用は実際には理由のため@dbenham's answerを参照してください、この場合には動作しません。

^をドロップし、2行をマージ:

falsey && echo nope 

のか&&の前にスペースを追加:

falsey^
&& echo nope 

これら3つの各オプションが正しくnopeを印刷されません。しかし、cmd.exeが実行しているコマンドを出力すると、余分なスペースが残っています。

なぜこれらの余分なスペースが挿入されていますか、私のコードを軽度に不自然な形に変えずにcmd.exeを中断させないようにするにはどうすればいいですか?

+2

改行をエスケープし、次の行に '&&'を付けると、どうなるでしょうか? 'false && echo nope'または' falsey &&(\ n echo nope \ n) '(' \ n'は改行)は標準的な規則です。あなたがしていることは、連合で文章を始めるように感じる。そしてそれは厄介です。 – rojo

+0

バッチファイルを編集するためにどのテキストエディタを使用していますか? –

+0

@rojoこれは私が実際に使っている線がかなり長いためです。 '&&'を次の行の先頭に置くと、実行が前の行の実行に依存することが明らかになります。 – 8bittree

答えて

8

The line continuation ^ escapes the first character on the next lineのように、最初の&はリテラルとして扱われ、falseyの引数として渡されます。 2番目の&は、単純なコマンド連結として扱われます。

falsey &&^ 
echo nope 

またはあなたが&&

falsey^
&& echo nope 

の前にスペースを置くことができる:&&は条件付きコマンドの連結として扱われるように取得する

一つの簡単な解決策は、前の行に&&を置くことですもう一つの選択肢は、jebがリンクされた回答で指摘しているリダイレクトトリックを使用することですが、そのトリックは使用しません。


「ソリューション」に関しては、"&&"と引用されています。あなた自身をだますことになります。偽が失敗したときに動作するように見えます。OUTPUT - - 最初"がエスケープされているので&&作品は、&&ので引用されていないことを

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

echo ONE^
"&&" echo TWO 

:あなたのコマンドが成功した場合しかし、あなたは問題があります。あなたは"&&"

echo ONE^ 
"&&" echo TWO 

の前にスペースを追加した場合、今スペースがエスケープされており、"&&"が引用されているので、あなたは、次の

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

を取得します。


あなたのコメントについて、あなたはそれらの余分なスペースを無視することができます - 彼らはECHOがONのとき、パーサはラインの表示方法の成果物です。パーサーは、行を大きく並べ替えることがよくありますが、通常は結果には影響しません。

例えば

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

--OUTPUT--

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

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

エコーSETラインが完全に再配置される方法に注意してください。リダイレクションは圧縮され、リダイレクションの前にスペースを入れてステートメントの最後に移動します。スペースは割り当てに含まれると思うかもしれませんが、それはそうではないことがわかります:-)

あなたが持っている唯一の時間は、コマンドがパイプで使用されている場合です。例えば

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

--OUTPUT--

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

あなたはSET値に含まれている単一の不要な余分なスペースがあることがわかります。これは、パイプがどのように実装されるかのアーティファクトです。各側は新しいCMD.EXEプロセスで実行され、その行は複数回解析されます。左のcmd.exeに渡されたコマンドラインを表示するには、%CMDCMDLINE%を使用してスペースがどこから来ているかを確認します。

(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?を参照してください。特に、選択された答えに注意を払って、何が起こっているのかをよく説明してください。

+0

'^'がなく、すべてが1行である場合の余分なスペースはどうですか? – 8bittree

+0

@ 8bittree - 余分なスペースは、コマンドがエコーされたときにのみ出力されます(ECHOがオン)。それらはパーサのアーティファクトです。スペースは実際にコマンドに渡されないので、影響はありません。影響を受けるのは、コマンドが複数回解析され、パイプで使用される場合など、新しいcmd.exeプロセスでコマンドが実行されるときだけです。 – dbenham

+0

@ 8bittree - 「余分なスペース」についてのより良い説明と、なぜ通常無視できるのかについては、最後の編集を見てください。 – dbenham

関連する問題