前書き

自動化Script作成時に、Bash (Shell Script)ではなく、RubyやPython3を用いた方がScriptのメンテナンス負荷が低くなります。自動化Scriptに使用するプログラミング言語変更を目的として、各言語の実装を比較します

本記事では、ヒアドキュメントの書き方を比較します。比較では、実装例および実行例をそれぞれ示します。

Bashではなく、RubyやPython3を使った方が好ましい理由は、以下の記事に記載しています。この記事には、各プログラミング言語の様々な実装(ディレクトリ操作やファイル操作など)を比較した他記事へのリンクを一覧にまとめています。

各言語のVersion

  • Bash:GNU bash, バージョン 5.0.3(1)-release
  • Ruby:ruby 2.5.5p157 (2019-03-15 revision 67260)
  • Python:Python 3.7.3

比較:ヒアドキュメントの書き方

ヒアドキュメントは、まとまった文字列を変数に保存して、ファイルや標準入出力に出力する際に使用する機会が多いです。

以下に、各言語の実装例および実行例を示します。

Bashの場合

#!/bin/bash

TEST="test"

# ヒアドキュメントの例(変数展開あり)
# 行頭に文字列終端文字列"_EOS_"が現れるまで、
# 複数行に渡って文字列を記載できる。
# "_EOS_"部分は任意の文字列。
cat << _EOS_
---
ヒアドキュメント内は、変数${TEST}も展開可能。
変数展開をエスケープする場合は、
\${TEST}のようにバックスラッシュ(\)を変数の前に記載する。
---
_EOS_
# 終端時の"_EOS_"は、行に単独で現れなければならない。
# 「行頭にスペース・タブを付与した場合」や「末尾にコメントを付与した場合」は、
# ヒアドキュメントの終端とみなされない。

# ヒアドキュメント例
#(「変数展開なし」かつ「ヒアドキュメントを変数に代入」)
STR=$(cat << "_EOS_"
---
二重引用符で終端文字列を囲むと、
変数${TEST}が展開されない。
---
_EOS_
)
echo "${STR}"

# ヒアドキュメント例(行頭のハードタブを無視)
# "<<"ではなく、"<<-"を使用する。
cat <<-_EOS_
---
<<-の場合、
	ハードタブは、無視される。
    スペースは、そのまま残る。
---
_EOS_

Rubyの場合

#!/usr/bin/env ruby

TEST = "test"

# ヒアドキュメントの例(変数展開あり)
# bashと基本的なルールは同じ。詳細はbashの例を参照。
# Rubyでは、"<<"と"_EOS_"の間にスペースがあるとエラー。
printf( <<_EOS_
---
ヒアドキュメント内は、変数#{TEST}も展開可能。
変数展開をエスケープする場合は、
\#{TEST}のようにバックスラッシュ(\\)を変数の前に記載する。
---
_EOS_
)

# ヒアドキュメント例
#(「変数展開なし」かつ「ヒアドキュメントを変数に代入」)
STR = <<'_EOS_'
---
引用符で終端文字列を囲むと、
変数#{TEST}が展開されない。
---
_EOS_
printf(STR)

# ヒアドキュメント例
#(終端文字列の前にスペースを入れるケース)
# "<<"ではなく、"<<-"を使用する。
printf( <<-_EOS_
---
<<-の場合、終端文字にスペースを入れられる。
	ハードタブは、そのまま残る。
        スペースは、そのまま残る。
---
_EOS_
)

# ヒアドキュメント例
#(ハードタブ・スペースを無視するケース)
# "<<-"ではなく、"<<~"を使用する。
printf( <<~_EOS_
---
<<~の場合、終端文字にスペースを入れられる。
	ハードタブは、無視される。
        スペースは、無視される。
---
        _EOS_
)

Python3の場合

#!/usr/bin/env python3

print('''\
---
ヒアドキュメント内は、変数{TEST}も展開可能。
変数展開をエスケープする場合は、
変数TESTを中括弧で囲まなければ良い。
---'''.format(TEST="test")
)

# ヒアドキュメント例
#(「変数展開なし」かつ「ヒアドキュメントを変数に代入」)
STR = r'''---
ヒアドキュメントの開始に"r"を付けると、
エスケープシーケンスが通常の文字列として扱われる。
---'''
print(STR)

# ヒアドキュメント例
#(終端文字列の前にスペースを入れるケース)
# .strip()で終端の空白を除去する。
print('''\
---
strip()を使うことで、終端文字にスペースを入れられる。
	ハードタブは、そのまま残る。
        スペースは、そのまま残る。
---
        '''.strip()
)

# ヒアドキュメント例
#(ハードタブ・スペースを無視するケース)
# .strip()でハードタブとスペースを除去する。
print('''\
---
replace()を使うことで、任意の文字を置換できる。
	今回の例ではハードタブは、無視(削除)される
        スペースは、無視(削除)される
---
        '''.replace("\t", "").replace(" ", "")
)

Bash、Ruby、Python3の実行例

$ ./bash.sh 
---
ヒアドキュメント内は、変数testも展開可能。
変数展開をエスケープする場合は、
${TEST}のようにバックスラッシュ(\)を変数の前に記載する。
---
---
二重引用符で終端文字列を囲むと、
変数${TEST}が展開されない。
---
---
<<-の場合、
ハードタブは、無視される。
    スペースは、そのまま残る。
---

$ ./ruby.rb 
---
ヒアドキュメント内は、変数testも展開可能。
変数展開をエスケープする場合は、
#{TEST}のようにバックスラッシュ(\)を変数の前に記載する。
---
---
引用符で終端文字列を囲むと、
変数#{TEST}が展開されない。
---
---
<<-の場合、終端文字にスペースを入れられる。
	ハードタブは、そのまま残る。
        スペースは、そのまま残る。
---
---
<<~の場合、終端文字にスペースを入れられる。
	ハードタブは、無視される。
        スペースは、無視される。
---

$ ./python.py 
---
ヒアドキュメント内は、変数testも展開可能。
変数展開をエスケープする場合は、
変数TESTを中括弧で囲まなければ良い。
---
---
ヒアドキュメントの開始に"r"を付けると、
エスケープシーケンスが通常の文字列として扱われる。
---
---
strip()を使うことで、終端文字にスペースを入れられる。
	ハードタブは、そのまま残る。
        スペースは、そのまま残る。
---
---
replace()を使うことで、任意の文字を置換できる。
今回の例ではハードタブは、無視(削除)される
スペースは、無視(削除)される
---