1. ホーム
  2. batch-file

Windows バッチの改行変数ハックの仕組みについて説明する。

2023-09-15 10:43:58

質問

どなたか、この仕組みを説明していただけませんか?

@echo off
REM Creating a Newline variable (the two blank lines are required!)
set NLM=^


set NL=^^^%NLM%%NLM%^%NLM%%NLM%
REM Example Usage:
echo There should be a newline%NL%inserted here.

が発する。

There should be a newline
inserted here.

から バッチファイルで改行をエコーする方法を教えてください。

どのように解決するのですか?

キャレットの挙動を利用したトリックです。

にも説明があります。 Windows Vista のバッチ (.bat) ファイルで長いコマンドを複数行に分割する

キャレットは次の文字へのエスケープ文字であったり、行末では複数行の文字として使われますが、これもほぼ同じです。

行末では、単に次の文字をエスケープします。 <Linefeed> しかし、隠された機能があり、もしエスケープされた文字が <LF> であった場合は無視され、次の文字が読み込まれてエスケープされますが、この文字は、たとえそれが <LF> .

これで

set NLM=^


rem Two empty lines are required here

NLM-Variableには、ちょうど1つの <LF> という文字が含まれています。 しかし、もしこれを echo Line1%NLM%Line2 のところでパースが止まってしまうので、失敗します。 <LF> .

しかし、これは動作します。

echo Line1^

Line2

そこで、行にエスケープされたラインフィードを追加する必要がありますが、これがNL-Variableです。 NL-Variableはたった3つの文字で構成されています。

NL=^<LF><LF> そして、これが展開されると、たった一つのエスケープされた <LF> として最初の <LF> は無視されます。

私の意見では、遅延展開で改行する方がエスケープする必要がないので、はるかに簡単です。

この例では %=EMPTY=% を空行の代わりに使っています(セルフコメントのため)。 =EMPTY= は存在できないので、空行に展開されます。

setlocal EnableDelayedExpansion
(set NLM=^
%=EMPTY=%
)
echo Line1!NLM!Line2

EDITです。 を使うと便利なヒントを追加する。 <LF>

1) 内で改行する。 echo

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
echo Line1!LF!Line2

2) 括弧ブロック内のコマンドを分割するのに使う

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
(
    echo Line1%LF%set x=4%LF%echo !x!%LF%
)

3) FOR /Fループで(ほぼ)空のEOL-charcterを作成します。 として <LF> が行の区切り文字で、EOL は <LF> は空のものと同じです。

FOR /F ^"eol^=^

delims^=^" %%a in (myFile.php) do echo %%a

4) FOR /Fループの中でテキストを分割するためにLFを使用する

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
set "var=Content1;Content2"
FOR /F "delims=" %%a in ("%var:;=!LF!%") do (
  echo %%a
)