bash スクリプトでヒアドキュメントを変数に格納したいけどヒアドキュメントの中にカッコがあってエラーになってしまう場合の対策
最近ブログの記事タイトルが長い気がするのでなんとか短めに抑えたいのですがなんとかならないものでしょうかね。
さて、昨年あたりから shellcheck というツールを使ってシェルスクリプトの lint をするようにしたので自分の shell 力が少し上がった気がしているのですが、以下のようなありがちなコードの解決策が覚えられそうになかったのでメモしておきます。
やりたいことは、read コマンドを使ってユーザーに複数の選択肢を提示して選んでもらうというとてもシンプルな、よくありがちなことだと思います。
read コマンドには -p オプションがあり、ユーザーに対して何かのプロンプトを提示することができます。
そこで
read -r -p "$prompt" num
という感じでプロンプトを表示しつつ num という名前の変数に選択されたの番号を取得することを考えます。
prompt 変数にはメッセージを入れておきます。
たとえば、以下のようなプロンプトを表示させたい場合:
1) hoge 2) fuga 3) piyo choose a number (1-3) ?
変数 prompt には定石パターンとして以下のように $( ) と cat とヒアドキュメントを使って、
prompt=$(cat <<EOD 1) hoge 2) fuga 3) piyo choose a number (1-3) ? EOD )
という感じにすると思います。しかしこれは実は問題があります。 ヒアドキュメントの中に半角閉じカッコが入っていると、そこで $( が閉じられてしまって、その後シンタックスエラーなどが起こってしまうのです。
なお、` 〜 ` を使うと閉じカッコの問題は起こらないかもしれませんが、
prompt=`cat <<EOD ^-- SC2006: Use $(..) instead of legacy `..`.
というふうに shellcheck に警告されてしまいます。 shellcheck の説明 を読むと、` 〜 ` には POSIX で未定義動作があったり、独自のエスケープモードに入ってびっくりするような結果になったり、ネストさせるのが難しかったり、といったような弊害があるとのことです。
というわけで $( ) を使って以下のように書いてみるとやはり実行時にエラーになってしまいます。
$ cat paren.sh #!/bin/bash prompt=$(cat <<EOD 1) hoge 2) fuga 3) piyo choose a number (1-3) ? EOD ) read -r -p "$prompt" num echo "You chose $num" $ bash paren.sh paren.sh: line 4: hoge: command not found paren.sh: line 5: syntax error near unexpected token `)' paren.sh: line 5: `2) fuga'
これを回避するには、関数 を使って以下のようにします。
function get-msg() { cat <<EOD 1) hoge 2) fuga 3) piyo choose a number (1-3) ? EOD } prompt=$( get-msg ) read -r -p "$prompt" num echo "You chose $num"
get-msg 関数(名前はなんでも良いです)が cat とヒアドキュメントを使って問題となる閉じカッコを含む文字列を表示します。 それを $( ) の中で 呼び出すことで文字列を変数に格納します。 これにより、$( ) の中に閉じカッコが現れなくなるので問題が起こらなくなるというわけです。
[改訂新版] シェルスクリプト基本リファレンス ??#!/bin/shで、ここまでできる (WEB+DB PRESS plus)
- 作者: 山森丈範
- 出版社/メーカー: 技術評論社
- 発売日: 2011/04/27
- メディア: 単行本(ソフトカバー)
- 購入: 9人 クリック: 119回
- この商品を含むブログ (10件) を見る
- 作者: Cameron Newham,Bill Rosenblatt,株式会社クイープ
- 出版社/メーカー: オライリージャパン
- 発売日: 2005/10/27
- メディア: 大型本
- 購入: 7人 クリック: 138回
- この商品を含むブログ (47件) を見る
- 作者: Carl Albing,JP Vossen,Cameron Newham,株式会社クイープ
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/09/26
- メディア: 大型本
- 購入: 8人 クリック: 268回
- この商品を含むブログ (31件) を見る