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 の問題がなさそうなら、これでいってもいいかな。

本日のTrackBacks(全1件) []
_ daily memorandum 2.2.1 (2005-06-21 (Tue) 09:08)

[FreeBSD] topless が bash, pdksh で動かない件 すでに最新では直ってます。 最新版ではほかにも変更タフ゜ーリ入ってますし、そろそろ NEWS とか CHANGES とか CONTRIBUTORS とか、そういったファイルが必要だよねってことで、その辺を用意したら release となると思い..