13

SHIFTブロック内で使用しようとすると、IF予期しない結果が発生します。これを使用して:

@echo off

if "%1"=="/p" (
    echo %1
    shift
    echo "shifted"
    echo %1
)

私は以下を取得します:

C:\>ex.bat /p HAI
/p
"shifted"
/p

ただし、このコードを使用すると:

@echo off

echo %1
shift
echo "shifted"
echo %1

私はこれを得る:

C:\>ex.bat /p HAI
/p
"shifted"
HAI

2 番目の出力が必要ですが、論理ブロック内にあるため、ループすることができます。ここでジョンの答えに似たものを実装しようとしています: Using parameters in batch files at DOS command line、しかし私はいくつかの問題を抱えています。なぜこうなった?

4

4 に答える 4

14

%1行が解析されるときに が展開され、括弧で囲まれた IF 構造全体がすべて 1 回のパスで解析されるため、これは予想される動作です。したがって、新しい行が解析されるまで SHIFT の結果を見ることはできません。これは、括弧で囲まれたブロックを離れるまで発生しません。

を使用して環境変数を展開すると、同じ問題が発生します%var%SETLOCAL EnableDelayedExpansion環境変数を使用すると、 を使用して遅延展開を有効にし、次に を使用して問題を回避できます!var!。しかし、遅延拡張を使用してパラメーターを拡張する同等の方法はありません。

EDIT 2013-06-21 - 同等の方法はありませんが、比較的遅い単純な方法があります。

CALL を使用して%.

@echo off

if "%1"=="/p" (
    echo %1
    shift
    echo "shifted"
    call echo %%1
)



EDIT 2016-07-15 Vladislav の回答 のコードは、GOTO を使用してコード ブロックを終了した後、コード ブロック内でジャンプして戻ることができることを意味するため、悪い習慣です。それは単に機能しません。GOTO は、解析されたコード ブロックを即座に削除します。Vladislav のコードを次のように書いた方がよいかもしれません。

@echo off
if "%1"=="/p" (
  goto :true
  :true
  echo "%1"
  shift
  echo shifted
  echo "%1"
)

条件が FALSE の場合、ブロック全体がスキップされます。条件が 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
)

FALSE の場合、ELSE ブロックのみが実行されます。TRUE の場合、一番上のブロックが実行され、すぐに強制終了されます。コードの残りの部分が実行され、パーサーがコマンドを予期し、スタックにアクティブな括弧ブロックがない場合、REM として機能する) else (ため、行は無視されます。)

上で示したように (または Vladislav が行ったように)、括弧で囲まれたコード ブロック内のラベルに GOTO しないことを強くお勧めします。

以下は、同じことを行うためのより良い (より単純で誤解を招かない) 方法です。

@echo off
if not "%1"=="/p" goto :skip
echo "%1"
shift
echo shifted
echo "%1"

:skip

追加のラベルと GOTO を使用して、IF/THEN/ELSE の概念をサポートできます。

@echo off
if not "%1"=="/p" goto :notP
echo "%1"
shift
echo shifted
echo "%1"
goto :endIf

:notP
echo not /p

:endIf
于 2013-06-21T18:06:24.667 に答える