一部のシェルで動かないシェルスクリプト

  • 4
    いいね
  • 4
    コメント
この記事は最終更新日から1年以上が経過しています。

これ、正しく動きますか?

#! /bin/zsh

echo $(case 1 in 1) echo OK;; esac)

いや、シェルスクリプトにしなくてもそれぞれのシェルに切り替えてコマンド実行するだけで確かめられるのですが……。

旧バージョンbash
$ bash --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
$ echo 'echo $(case 1 in 1) echo OK;; esac)' | bash
bash: line 1: syntax error near unexpected token `;;'
bash: line 1: `echo $(case 1 in 1) echo OK;; esac)'
$ 
旧バージョンzsh
$ zsh --version
zsh 5.2 (i386-portbld-freebsd9.3)
$ echo '$(case 1 in (1) echo OK;; esac)' | zsh
zsh: command not found: OK
$ 

原因は、$()の中のcase文

調べてみて「あ〜そういうこと」と思いましたが、$()というサブシェル実行構文が、中のcase構文で出てくる条件指定の)を自分の閉じ括弧であると誤認識してしまうことが原因でした。

私は今のところ旧バージョンのbashとzshでだけこの現象を見つけましたが、シェルのパーサーが甘いと将来的にも起きそうなので気をつけようと思います。

対策:バッククォート囲み``に代える

上記シェルではいずれも、$()``に書き代えることで治まります。

バッククォートに代えれば大丈夫
$ echo 'echo `case 1 in 1) echo OK;; esac`' | bash
OK
$ echo 'echo `case 1 in 1) echo OK;; esac`' | zsh
OK
$ 

そもそも、新バージョンにすればいいのですが。特にBashは、ShellShock問題がありましたから当然更新しましたよね? ← お前はどうなんだ!

追記:
ShellShockパッチの当たった後の今でも現役なbashでもこの現象が起こることを教えてもらいました。(ありがとうございます、@akinomyogaさん)