シェルのコマンドで、オプションがたくさんあるときは、読みやすくするために改行することがあると思う。
somecommand --optionA=xxxx \
--optionB=yyyy \
--optionC=zzzz \
--optionD=wwww
しかし、これを部分的にコメントアウトする時(たとえばオプションの組み合わせを試す際)
somecommand --optionA=xxxx \
--optionB=yyyy \
# --optionC=zzzz \
--optionD=wwww
のようにコメントアウトして失敗した経験は、皆さんにはないだろうか?
echo での例示
たとえば、↓のようなシェルスクリプトを
#!/usr/bin/env bash
echo 'a' 'x' \
'b' 'y' \
'c' 'z' \
'd' 'w'
コメントアウトして
#!/usr/bin/env bash
echo 'a' 'x' \
'b' 'y' \
# 'c' 'z' \
'd' 'w'
のようにして実行すると、
$ ./sample.sh
a x b y
./sample.sh: line 6: d: command not found
$
と、このように。
コメントアウト以降が独立したステートメントとして扱われるため d
を実行しようとする。
この例では d
というコマンドがなかったから良いものの、
存在するようなケースでは致命傷を生む可能性がある。
回避策を考えてみた
よくある /* */
な範囲コメントアウトができれば、このような悲劇は避けられると思った。
1 行の範囲コメントを発明したい。
ヒアドキュメントを使う方法
シェルの範囲コメントアウトといえば、ヒアドキュメントとヌルコマンドを利用した方法が一般的だ。
クオートで囲めば、変数やコマンド置換の評価も止められる。
:<<'EOT'
somecommand
foo
bar
buzz
EOT
でもコレは複数行が前提に成ってしまうのでダメだ。
これをオプションの中でやりたい。
外側を式で囲む
行を $(:
と )\
で囲む戦法を思いついたのでやってみた。
コマンド置換でヌルコマンドに対して引数が渡るので、置換後は空になるというわけだ。
コマンド置換はダブルクォートで囲まないので、空文字列が挿入されることもない。
#!/usr/bin/env bash
echo 'a' 'x' \
'b' 'y' \
$(: 'c' 'z' \ )\
'd' 'w'
$ ./sample.sh
a x b y d w
$
これは一見よさそうだ。
このパターンだけならこれで正解。
さらなる問題
しかし ↑ ではコメントアウト対象が単なる文字列だったので済んだが、元のスクリプトが次のような例だとダメだ。
#!/usr/bin/env bash
function inc () {
echo 'called!' "$*" > /dev/tty
}
echo 'a' "$(inc 'x')" \
'b' "$(inc 'y')" \
'c' "$(inc 'z')" \
'd' "$(inc 'w')"
これを上記の方法で c の行をコメントアウトして実行してみよう。
#!/usr/bin/env bash
function inc () {
echo 'called!' "$*" > /dev/tty
}
echo 'a' "$(inc 'x')" \
'b' "$(inc 'y')" \
$(: 'c' "$(inc 'z')" \ )\
'd' "$(inc 'w')"
$ ./sample2.sh
called! x
called! y
called! z
called! w
a b d
$
ご覧のとおり、 c の行の $(inc 'z')
は評価されてしまっている。
こいつもトラップだ。
短絡評価する
最終的に思いついたのがコレ
$(:||:
と )\
で囲む方法
#!/usr/bin/env bash
function inc () {
echo 'called!' "$*" > /dev/tty
}
echo 'a' "$(inc 'x')" \
'b' "$(inc 'y')" \
$(:||: 'c' "$(inc 'z')" \ )\
'd' "$(inc 'w')"
$ ./sample2.sh
called! x
called! y
called! w
a b d
$
これで平和になった…。
まとめ
これが今思いついている中では、最も万能な 1 行コメントアウトの方法だと思う。(たぶん)
それにしても、あまりに技巧的なやり方過ぎてしっくりこない……。
そしておそらく、この解決法にもさらなる落とし穴があるに違いない。(落とし穴募集)
ところで
$(:||: )\
ちょっとかわいい顔文字みたいだと思いません?