はじめに
バッチファイルでヒアドキュメントのようなことをするサンプルです。
例として、ヒアドキュメントをrubyに渡して実行させています。
改行の環境変数の遅延展開を使った場合(OK)
改行を環境変数LFで定義して、遅延展開で含めたものをechoすると複数行で表示される。
バッチファイルでは^の次の文字はそのままの文字として使われるので、^の次の文字である改行がLFの値として設定される。(^+改行+改行+改行)
@echo off
setlocal enabledelayedexpansion
set LF=^
echo ^
puts a=1!LF!^
puts a+1!LF!^
puts a+2
echo ===
set STR=^
puts a=1!LF!^
puts a+1!LF!^
puts a+2
echo !STR!
puts a=1
puts a+1
puts a+2
===
puts a=1
puts a+1
puts a+2
改行ありの環境変数値をechoで出力してパイプで渡す場合(NG)
改行を含む環境変数値をechoしても1行目しか渡されない。
@echo off
setlocal enabledelayedexpansion
set LF=^
echo ^
puts a=1!LF!^
puts a+1!LF!^
puts a+2!LF!^
| ruby
echo ===
set STR=^
puts a=1!LF!^
puts a+1!LF!^
puts a+2
echo !STR! | ruby
1
===
1
改行ありの環境変数値をsetで出力してパイプで渡す場合(OK)
setコマンドなら複数行を渡せるが注意が必要。
- 「環境変数名=」が表示されるのでその部分を1行目にしてmoreで読み飛ばす。
- setに指定した名前で始まるすべての環境変数が出力されるため、名前の重複がないようにする。
@echo off
setlocal enabledelayedexpansion
set STR1=XXX
set LF=^
set STR=!LF!^
puts a=1!LF!^
puts a+1!LF!^
puts a+2
set STR | more +1
echo ===
set STR | more +1 | ruby
puts a=1
puts a+1
puts a+2
STR1=XXX
===
1
2
3
Traceback (most recent call last):
-:4:in `<main>': uninitialized constant XXX (NameError)
環境変数を読み込めるコマンドを使ってパイプ渡し(OK)
echoの代わりに環境変数を読み込めるコマンドを使って標準出力する。パイプを使わなくてもrubyならevalで実行できる。
@echo off
setlocal enabledelayedexpansion
set LF=^
set STR=^
puts a=1!LF!^
puts a+1!LF!^
puts a+2
ruby -e "puts ENV['STR']" | ruby
echo ===
ruby -e "eval(ENV['STR'])"
1
2
3
===
1
2
3
ヒアドキュメントのサブルーチン化(OK)
call :labelによるサブルーチンでのヒアドキュメント。
@echo off
setlocal enabledelayedexpansion
call :HEREDOC "%~f0" VAR1 & goto :VAR1
puts a=1
puts a+1
puts a+2
:VAR1
echo !VAR1!
echo ===
set VAR1 | more +1 | ruby
call :HEREDOC "%~f0" VAR2 & goto :VAR2
puts a=10
puts a+1
puts a+2
:VAR2
echo !VAR2!
echo ===
set VAR2 | more +1 | ruby
exit /b
:HEREDOC
set FILE=%1
set VAR=%2
set FLAG=N
for /f "usebackq tokens=1* delims=" %%I in (`more %FILE%`) do (
set WORK=%%I
if "!WORK!" == "!WORK::%VAR%=!" (
if "!FLAG!" == "Y" set %VAR%=!%VAR%!^
%%I
) else (
if "!FLAG!" == "Y" goto :END_HEREDOC
set FLAG=Y
)
)
:END_HEREDOC
exit /b
puts a=1
puts a+1
puts a+2
===
1
2
3
puts a=10
puts a+1
puts a+2
===
10
11
12
バッチファイルの後方にスクリプトを配置(OK)
バッチファイル内にキーワードを書き、そのキーワードから後ろにスクリプトを書く。
キーワードの位置はfindstrで行番号を取得し、moreでそれ以降を読み取る。
@echo off
for /f "usebackq tokens=1 delims=:" %%I in (`findstr /n /b :script "%~f0"`) do set N=%%I
more +%N% "%~f0"
echo ===
more +%N% "%~f0" | ruby
exit /b
:script
puts a=1
puts a+1
puts a+2
puts a=1
puts a+1
puts a+2
===
1
2
3
番外:改行なしの1行渡し(OK)
複数行にこだわらず、改行なしの1行で渡す方法もある。
^の後の文字はそのまま使われるため、|の前に空白が必要。
@echo off
echo ^
puts a=1;^
puts a+1;^
puts a+2;^
| ruby
1
2
3