1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Windowsのバッチファイルでヒアドキュメントのあれこれ

Last updated at Posted at 2023-01-08

はじめに

バッチファイルでヒアドキュメントのようなことをするサンプルです。
例として、ヒアドキュメントを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
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?