0

output.txt と test.bat の 2 つのファイルがあります。output.txt には「1 2 3 4」という 1 行しかなく、test.bat の内容は次のとおりです。

@echo off
set condition=1

if "%condition%" == "1" (
    for /F "tokens=1,2,3,4* delims= " %%a in (output.txt) do set variable=%%a
    echo %variable%
)
pause

run test.bat は何もエコーしません。しかし、少し変更すると、次のようになります。

@echo off
set condition=1
for /F "tokens=1,2,3,4* delims= " %%a in (output.txt) do set variable=%%a
echo %variable%
if "%condition%" == "1" (
    for /F "tokens=1,2,3,4* delims= " %%a in (output.txt) do set variable=%%a
    echo %variable%
)
pause

'1' を 2 回エコーします。変?バグ?

4

2 に答える 2

4

2 つのスクリプトのどちらも、あなたが思っているようなことをするとは思いません (具体的には、2 番目のスクリプトは、最初のスクリプトの後に実行するという理由だけでそのように機能します)。

なぜそのように振る舞うのですか?

注意すべき重要なことは、遅延変数展開がオンになっていない限り、変数はそのコマンドが実行される前に各コマンドに対して評価されるということです。括弧内のコマンド ブロック全体が 1 つのコマンドと見なされるIFため、これは を使用する場合に特に重要です。

説明する:

SET foo=
ECHO foo = %foo%
IF 1==1 (
    SET foo=bar
    ECHO foo = %foo%
)

上記のスクリプトは次を出力します。

foo =
foo =

その理由は、条件が

IF 1==1 SET foo=bar && ECHO foo = %foo%

これは 1 つのコマンドにすぎないため、変数は実行前に 1 回だけ展開されます (特に、 の後SETと の前では展開されませんECHO)。

これは、スクリプトでも発生します。はブロック内%variable%で設定およびエコーされるため、 はECHO実際%variable%にはブロックに入る前の値で動作するため、「現在の」値は表示されません。

修正方法は?

遅延変数展開の問題を解決する

これには 2 つの方法があります。簡単な方法は、遅延変数展開を有効にし、代わりに次SETLOCALの構文で変数を参照することです。!var!%var%

SETLOCAL ENABLEDELAYEDEXPANSION
SET foo=
ECHO foo = !foo!
IF 1==1 (
    SET foo=bar
    ECHO foo = !foo!
)

上記のスクリプトは次を出力します。

foo =
foo = bar

コマンドブロックを分割して問題を解決する

これを行う別の方法もあります。変数は、各コマンド (またはブロック) が実行される前に一度展開されることに注意してください。SETしたがって、と の間で展開を発生させたい場合はECHO、ブロックを分割することで発生させることができます。これを行うには、テストを元に戻し、NOTa を使用してGOTO、「成功」ブランチ内の以前のコードをスキップします。

SET foo=
ECHO foo = %foo%
IF NOT 1==1 GOTO :proceed
SET foo=bar
ECHO foo = %foo%
:proceed

上記のスクリプトは、次の出力も行います。

foo =
foo = bar

あなたの例にソリューションを適用する

2 つのアプローチは、次のいずれかに変換されます。

SETLOCAL ENABLEDELAYEDEXPANSION
IF "%condition%" == "1" (
    FOR /F "tokens=1,2,3,4* delims= " %%a in (output.txt) DO SET variable=%%a
    ECHO !variable!
)

またはこれ:

IF NOT "%condition%" == "1" GOTO :proceed
FOR /F "tokens=1,2,3,4* delims= " %%a in (output.txt) DO SET variable=%%a
ECHO %variable%
:proceed
于 2012-07-05T10:29:41.373 に答える
2

バグではありません。これは、CMD が変数展開を実装する方法の副作用です。Raymond Chen の記事がここにあります。

http://blogs.msdn.com/b/oldnewthing/archive/2006/08/23/714650.aspx

具体的には、最初の例では、%variable%展開された時点で、設定されていません。

于 2012-07-05T10:20:51.733 に答える