daily memorandum 2.3.0
CBUG | FreeBSD | Hiki | Knoppix | Mac | Ruby | W-ZERO3 | Windows | ad | amd64 | ks | linux | momonga | net | print | security | tdiary | unix | www | 会社 | 鯖缶 | 全学ゼミ | 本
2005-06-19 (Sun)
_ [unix] topless-1.41 は bash, pdksh で動きません!
tamo さん からの報告。topless-1.41 を bash や pdksh で使おうとすると、
% bash `which topless` ps axuww /usr/local/bin/topless: line 190: syntax error near unexpected token `;;' /usr/local/bin/topless: line 190: ` ;;' stty: illegal option -- usage: stty [-a|-e|-g] [-f file] [options]
% ksh `which topless` ps axuww /usr/local/bin/topless[190]: syntax error: `;;' unexpected
って感じでエラーが出て動きません。
$() の中に case の ) があると、それが $( の閉じ括弧と認識されてしまうみたい。 簡単なテストをしてみたところ、FreeBSD の /bin/sh (ash) は OK, bash と pdksh は NG でした。
% sh -c 'b=$(case a in a) echo a;; esac); echo b' b % bash -c 'b=$(case a in a) echo a;; esac); echo b' bash: -c: line 0: syntax error near unexpected token `;;' bash: -c: line 0: `b=$(case a in a) echo a;; esac); echo b' % ksh -c 'b=$(case a in a) echo a;; esac); echo b' ksh: syntax error: `;;' unexpected
SUS v2 ではどうなのか?
SUS v2 の Shell Command Language を読んでみると、 Command Substitution のところに
With the $(command) form, all characters following the open parenthesis to the matching closing parenthesis constitute the command. Any valid shell script can be used for command, except: * a script consisting solely of redirections produces unspecified results * see the restriction on single subshells described below.
とあるし、もう少し下の方で
the new $() form can process any kind of valid embedded script
と言ってるので、$() の中で case 文を書くというのは間違いではなさそう。
実装はどうなってるのか?
あまりマジメに見てないけど、bash や pdksh の parser を見てみると、 $( の閉じ括弧を探すのに、単純に ( と ) の数を数えてるだけっぽい。 「今 case 文の中にいるから、この ) はカウントしちゃいけないんだ」 とか、そういう判定はしてないみたい。
当然 ) がコメント行にあるかどうかとかも見てないので、 bash, pdksh では次の例もエラーになります (ash は問題なし)。
% cat > test.sh b=$( # ) echo a) echo $b ^D % bash test.sh test.sh: line 3: syntax error near unexpected token `)' test.sh: line 3: `echo a)' % ksh test.sh test.sh[3]: syntax error: `)' unexpected % sh test.sh a
コレ、SUS v2 に載ってる次の例の変形版です。 「正しく動作すべき」となってるので、動いて欲しいところなのだが…
echo $( echo abc # a comment with ) )
対処法
bash, pdksh の parser を書き直すのもめんどいし、 ほかにも問題のある実装があるかもしれないので、 topless 側で対処した方がよさげ。
Case Conditional Construct を見ると、
case ... in (hoge) ....;; esac
って感じで、case 文の pattern 部を ( で始めてもいいらしい。 少なくとも bash, pdksh, ash では問題なし。 portability の問題がなさそうなら、これでいってもいいかな。
[FreeBSD] topless が bash, pdksh で動かない件 すでに最新では直ってます。 最新版ではほかにも変更タフ゜ーリ入ってますし、そろそろ NEWS とか CHANGES とか CONTRIBUTORS とか、そういったファイルが必要だよねってことで、その辺を用意したら release となると思い..