^
エスケープ シーケンスを回避する方法があります。
遅延展開で変数を使用できます。以下は、小さなバッチ スクリプトのデモです。
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
echo !line!
または、FOR /F ループを使用することもできます。コマンドラインから:
for /f "delims=" %A in ("<html>") do @echo %~A
またはバッチスクリプトから:
@echo off
for /f "delims=" %%A in ("<html>") do echo %%~A
これらのメソッドが機能する理由は、遅延展開と FOR 変数展開の両方が<
、>
、&
、|
、&&
などの特殊な演算子||
が解析された後に発生するためです。Windows コマンド インタープリター (CMD.EXE) はどのようにスクリプトを解析しますか?を参照してください。詳細については。
sin3.14 は、パイプには複数のエスケープが必要になる可能性があると指摘しています。例えば:
echo ^^^<html^^^>|findstr .
パイプに複数のエスケープが必要な理由は、パイプの両側が新しい CMD プロセスで実行されるため、行が複数回解析されるためです。パイプされたコード ブロック内で遅延展開が失敗するのはなぜですか?を参照してください。Window のパイプ実装の多くの厄介な結果の説明について。
パイプを使用するときに複数のエスケープを回避する別の方法があります。独自の CMD プロセスを明示的にインスタンス化し、単一のエスケープを引用符で保護できます。
cmd /c "echo ^<html^>"|findstr .
遅延拡張手法を使用してエスケープを回避したい場合は、さらに驚きがあります (CMD.EXE の設計の専門家であれば驚かないかもしれませんが、このことを説明する公式の MicroSoft ドキュメントはありません)。
パイプの各側は独自の CMD.EXE プロセスで実行されますが、プロセスは遅延拡張状態を継承しないことに注意してください。デフォルトはオフです。そのため、独自の CMD.EXE プロセスを明示的にインスタンス化し、/V:ON オプションを使用して遅延展開を有効にする必要があります。
@echo off
setlocal disableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo !test!|findstr .
親バッチ スクリプトでは遅延拡張がオフになっていることに注意してください。
しかし、親スクリプトで遅延展開が有効になっていると、すべてがうまくいきません。以下は機能しません。
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
REM - the following command fails
cmd /v:on /c echo !test!|findstr .
問題は、が親スクリプトで展開されているため、新しい CMD プロセスが保護されていないand!test!
を解析しようとしていることです。<
>
をエスケープすることもできますが、が引用され!
ているかどうかに依存するため、注意が必要です。!
引用されていない場合は、二重エスケープが必要です。
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c echo ^^!test^^!|findstr .
引用されている場合は、単一のエスケープが使用されます。
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
cmd /v:on /c "echo ^!test^!"|findstr .
しかし、すべてのエスケープを回避する驚くべきトリックがあります。パイプの左側を囲むことで、親スクリプトが!test!
時期尚早に展開するのを防ぎます。
@echo off
setlocal enableDelayedExpansion
set "line=<html>"
(cmd /v:on /c echo !test!)|findstr .
しかし、括弧が使用されると、バッチ パーサーが最後に余分な (おそらく不要な) スペースを導入するため、それもただの昼食ではないと思います。
バッチ スクリプトは楽しいものではありません ;-)