これは、行が解析されたときに%1
が展開され、括弧で囲まれたIF構文全体がすべて1回のパスで解析されるため、これは予想される動作です。したがって、改行が解析されるまではSHIFTの結果を見ることはできません。これは、括弧で囲まれたブロックを終了するまで発生しません。
%var%
を使用して環境変数を展開しても同じ問題が発生します。環境変数を使用すると、SETLOCAL EnableDelayedExpansion
を使用して遅延拡張を有効にしてから、!var!
を使用して問題を回避できます。しかし、遅延拡張を使用してパラメータを拡張する方法はありません。
EDIT 2013-06-21 - これに匹敵する方法はありませんが、比較的遅い簡単な方法があります。
CALLを使用して%
を倍増させると、回線を強制的に再解析することができます。それはあなたがそれを残すためにGOTOを使用した後、あなたは、コードのブロック内でバックジャンプすることができることを意味して
@echo off
if "%1"=="/p" (
echo %1
shift
echo "shifted"
call echo %%1
)
EDIT 2016年7月15日 code in Vladislav's answerは、悪い習慣です。それは単に機能しません。 GOTOは、解析されたコードブロックを直ちに殺します。条件はその後、ブロック全体がスキップされ、FALSEの場合
@echo off
if "%1"=="/p" (
goto :true
:true
echo "%1"
shift
echo shifted
echo "%1"
)
:あなたはだけでなく、ウラジスラフのコードを書かれているかもしれません。 条件がTRUEの場合、GOTOは直ちにブロックを強制終了し、実行は通常:trueラベル(ブロックコンテキストなし)で正常に実行されます。最後の余分な)
は単に無視されます。
この構文でELSEを追加することはできません。次のような結果は得られません。
@echo off
if "%1"=="/p" (
goto :true
:true
echo "%1"
shift
echo shifted
echo "%1"
) else (
echo This will execute regardless whether arg1 is /p or not
)
偽の場合、ELSEブロックだけが実行されます。 TRUEの場合、先頭のブロックが実行され、すぐに終了します。コードの残りの部分が実行され、) else (
行は無視されます。これは、パーサーがコマンドを期待していて、アクティブなカッコブロックがスタックにない場合、がREMとして機能するためです。
上記のように(またはVladislavが行ったように)括弧で囲まれたコードブロック内にラベルを絶対入れないことを強くお勧めします。以下は
同じことを行うには良い(単純で誤解を招くない)方法です:
@echo off
if not "%1"=="/p" goto :skip
echo "%1"
shift
echo shifted
echo "%1"
:skip
あなたは
@echo off
if not "%1"=="/p" goto :notP
echo "%1"
shift
echo shifted
echo "%1"
goto :endIf
:notP
echo not /p
:endIf
[シフトはバッチスクリプトでは機能しません] http://social.technet.microsoft.com/Forums/scriptcenter/en-US/7bbbe8df-e3c0-46ab-aede-396c2b6f6184/shift-doesnt-work-in-batch-script) – piebie