遅延拡張と変数置換の問題

遅延拡張と変数置換の問題

ファイルへのファイル パスを含む 5 つの静的セット変数を切り替えINI、それを読み取って、置換する特定の文字列を検索するバッチ スクリプトがあります。

私の問題は、上記の置換を実行してファイルをディスクに書き戻した後、INI ファイル内のすべてのインスタンスがサニタイズされ、!その結果プログラムが壊れてしまうことです。

マークは DelayedExpansion によって置き換えられていると思います!が、ここでのタスクを実行するにはそれが必要です。問題のある関数のコピーを添付しますので、誰かがこの問題を解決するのを手伝ってくれると大変ありがたいです。

私は何日もこのことに対する答えを見つけようと必死です…

FOR %%A IN (1 2 3 4 5) DO (
    SET CFG_A=!CFG_%%A!
    IF "%DEBUG%"=="1" ECHO !CFG_A!
    FOR /f "delims=" %%i IN ('type "!CFG_A!" ^& break ^> "!CFG_A!" ') DO (
        SET "line=%%i"
        SETLOCAL enabledelayedexpansion
        SET "line=!line:%IP_V%=%IP%!"
        >>"!CFG_A!" echo(!line!
        ENDLOCAL
    )
)

答え1

明らかに、投稿されたコード全体にわたって遅延展開があり、遅延展開は FOR 変数展開の後に発生します。したがって、%%i遅延展開が有効になっているため、 の値は破損しています。

1 つの解決策は、内部ループ内に追加の SETLOCAL / ENDLOCAL を配置して、%%i展開中に遅延展開を一時的に無効にすることです。

また、ファイルを TYPE する必要はなく、空の出力ファイルを作成するためにリダイレクトされた BREAK や、ループ内で追加のリダイレクトを行う必要もありません。単に FOR /F にファイルを直接読み込ませ、内部ループの外側で 1 回リダイレクトさせるだけです。確かに、一時的な新しいファイルに書き込み、結果を元の名前に移動する必要があります。しかし、この方がはるかに効率的 (高速) です。

FOR %%A IN (1 2 3 4 5) DO (
  IF "%DEBUG%"=="1" >&2 ECHO(!CFG_%%A!
  (FOR /f "usebackq delims=" %%i IN ("!CFG_%%A!") DO (
    SETLOCAL disableDelayedExpansion
    SET "line=%%i"
    SETLOCAL enableDelayedExpansion
    SET "line=!line:%IP_V%=%IP%!"
    echo(!line!
    ENDLOCAL
    ENDLOCAL
  ))>"!CFG_%%A!.new"
  MOVE /Y "!CFG_%%A!.new" "!CFG_%%A!" >nul
)

注 - 私はテキストファイルをバッチで編集するのが本当に嫌いです。代わりに、JREPL.BAT - XP 以降の Windows マシンでネイティブに実行されるハイブリッド JScript/バッチ ユーティリティ:

FOR %%A IN (1 2 3 4 5) DO CALL JREPL "%IP_V%" "%IP%" /L /I /F "!CFG_%%A!" /O -

はるかにシンプルで、高速で、信頼性も高くなります :-)

関連情報