パスワードを忘れた? アカウント作成
3462 story

bashがマルチバイト文字に正式対応 83

ストーリー by Oliver
#!/usr/bin/hakushu 部門より

kubota 曰く、 "多くの Linux ディストリビューションで標準シェルとして採用されている bash のバージョン 2.05b が 17 日にリリースされました。最大の特徴は、同日にリリースされた readline バージョン 4.3 と組み合わせることで、EUC-JP、UTF-8 などのマルチバイト文字の入力に対応したことです。カーソル移動、挿入、削除、行あふれ処理などが、UTF-8、EUC-JP などのマルチバイト文字を含んでいても正しく処理されます。
bash/readline で日本語を扱うためのパッチは何種類か存在していました。が、そのなかには UTF-8 のみしか扱わない (EUC-JP などは扱わない) ものもあり (例えば Bruno Haible さんのパッチ)、どのパッチが採用されるかが関心の的でした。が、今回、IBM のパッチが採用されたことにより、EUC-JP を含む様々なエンコーディングに晴れて対応することとなりました。
もちろん、使用エンコーディングはLC_CTYPE ロケールによって決定されるので、bash のためだけにわざわざ設定を書く必要がありません。これで、日本語を含むファイル名を扱ったり、日本語文字列を用いて grep を使ったりといったことが、ずいぶんと楽にできるようになります。"

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • 重い (スコア:3, 興味深い)

    by manba256 (10135) on 2002年07月23日 5時27分 (#131152) ホームページ 日記
    ただでさえメモリ食うし、重いbashがさらに肥大化。
    そんなに多バイト文字つかいたいんですか?

    まあ、メモリ一桁メガバイトの住人のたわごとか。
    --
    ------------------------- Excess and Obsolete
    • 軽いシェル (スコア:4, 参考になる)

      by kubota (64) on 2002年07月23日 9時21分 (#131219) ホームページ 日記
      多機能がいい、というユーザと、軽いのを求めるユーザとを、 両方を満足させるのは難しいことです。 せいぜい、コンパイルオプションで対応する程度です。 ただでさえ重いとのことですので (たしかに、メモリ1桁メガバイトだとつらいでしょう)、 今さらマルチバイト機能だけを 外したところであまり足しにならないかもしれませんが、 いちおう、#if defined (HANDLE_MULTIBYTE) という行がソースには多数見られます (が、 どうやらこれは ./configure へのオプションでは決められなくて、 自動的に決定されるようです)。

      ちなみに、HANDLE_MULTIBYTE を見付けるためにソースを漁っている 最中に、mbstate_t が多数使われていることにも気付きました。 おそらく、stateful なエンコーディング (ISO-2022-JP など) にも対応しているのではないかと思います。 (使う人は、いるのかなあ)

      ちなみに、ぼくはメモリ 12MB のマシンを持っていますが、 bash が重いと思ったことはありませんが、 さすがに emacs は重いと思いました。

      軽いシェルですが、NetBSD の sh (Debian では ash という名前でパッケージングされています) は、 POSIX シェルです (#!/bin/sh として使える) が、 非常に軽いですよ。そのかわり、機能がかなり制限されますが。

      親コメント
      • Re:軽いシェル (スコア:2, 参考になる)

        by Anonymous Coward on 2002年07月23日 15時38分 (#131519)
        OpenBSD の /bin/sh は pdksh ベースだが、これもなかなか軽い。FreeBSD の /bin/sh は NetBSD と同じく ash ベースだが、 ~user の展開で NIS/YP も引くので static link されたバイナリサイズはでかい。

        ash は POSIX/SUSv3 には準拠していないが、 FreeBSD の /bin/sh は FreeBSD C99 & POSIX Conformance Project [freebsd.org] で準拠のための作業が進行中。NetBSD とFreeBSD では変更を相互にマージしている。

        POSIX には不備やほとんど無意味な規定もあるから完全準拠の是非は微妙だが、可能な範囲で擦り寄ることは大事、かな。
        親コメント
      • by famao (3403) on 2002年07月23日 23時45分 (#131818) ホームページ
        >ちなみに、HANDLE_MULTIBYTE を見付けるためにソースを漁っている 最中
        >に、mbstate_t が多数使われていることにも気付きました。 おそらく、
        >stateful なエンコーディング (ISO-2022-JP など) にも対応しているので
        >はないかと思います。 (使う人は、いるのかなあ)

        Linux上の話に限定してしまえば、bashがstatefulなエンコーディングをサポートしていようがいまいがglibcがそもそもstatefulなエンコーディングをサポートしていないはずなので関係ないと思います。が、世の中にはLinux以外のOSも数多く存在してますので、使う人もいると思います。

        今は亡きKondaraにおいてこのパッチを採用した際に、パフォーマンスが劇的に悪くなった、と文句しこたまいわれたりしたので、1バイトで事足りるようなロカールの場合にはマルチバイト文字ワイド文字の変換をスキップするようにした(他にword wrapやいくつかのバグつぶし)パッチをIBMの方に送付したのですが、この時に「mbstate_tを初期化してないためにstatefulなエンコーディングで正常に動作しません。」と注意された記憶があります。
        親コメント
        • by Anonymous Coward on 2002年07月24日 13時39分 (#132156)
          famaoさん> 「mbstate_tを初期化してないためにstatefulなエンコーディングで正常に動作しません。」

          mbrtowc() などの再開始可能な関数を使うなら,別にstatefulなエンコーディングじゃなくても,最初にシフト状態は初期化せねばならないかと。

          あと,

          kubotaさん> ちなみに、HANDLE_MULTIBYTE を見付けるためにソースを漁っている 最中
          kubotaさん> に、mbstate_t が多数使われていることにも気付きました。 おそらく、
          kubotaさん> stateful なエンコーディング (ISO-2022-JP など) にも対応しているので
          kubotaさん> はないかと思います。 (使う人は、いるのかなあ)

          mbstate_t があるからといって、stateful encoding 対応というわけではないですね。
          mbrtowc() を例にとると以下のような使い方かもしれないからです。

          mbrtowc()の戻り値は、
            与えられたバイト列がワイド文字に変換するのに何バイトか足りなくて変換できないなら(size_t)-2
            与えられたバイト列の後にどんなバイトが来ようがもはやワイド文字に変換できないなら(size_t)-1
          mbtowc() の戻り値は
            とにかく変換に失敗すれば(size_t)-1

          だから、mbrtowc()を使えば、以下のようにどっかから1byteずつ取ってきて、文字に変換するという方法が使えますが,mbtowc()ではできません。

          *) get_one_byte()はどこぞから1byteとってくる関数とします。

          char *str;
          int num;
          wchar_t wc;
          mbstate_t st;
          size_t ret;

          str = (char *) malloc (MB_CUR_MAX);

          memset (&st, '\0', sizeof(mbstate_t));
          for (num = 0; num MB_CUR_MAX; num++) {
                  str[num] = get_one_byte ();
                  ret = mbrtowc (&wc, str, MB_CUR_MAX, &st);

                  if (ret == (size_t)-2) {
                          memset (&st, '\0', sizeof(mbstate_t));
                          continue; /* ワイド文字に変換するにはバイトが足んない */
                  } else if (ret == (size_t)-1) {
                          エラー処理 /* ワイド文字に変換できなかった */
                  }
          }
          .
          .
          . ワイド文字を使った処理
          .
          .

          # ほかにも,スレッドセーフにしたいときなどが考えられます。
          親コメント
          • >mbrtowc() などの再開始可能な関数を使うなら,別にstatefulなエンコー >ディングじゃなくても,最初にシフト状態は初期化せねばならないかと。

            あ、すみません。もちろん最初にシフト状態は初期化しないといけません。私の送ったパッチはそこにバグをいれてしまっていたのですが、statelessなエンコーディングを利用している場合、すくすく動作してしまっていたので...。

            IBMの作成していた国際化部分では、mbrtowcの戻り値のチェックはそれほど厳密にやっていません。-1の場合も-2の場合も同様のものとして扱っています。
            僕が知る範囲では、mbrtowcをまっとうに利用しているアプリケーションは非常に少ないですね。IBMが作成しているパッチでは、全てmbrtowcを利用するようになっていて、企業としてのポリシーを感じます。

            > # ほかにも,スレッドセーフにしたいときなどが考えられます。

            少なくともglibcの実装では、mbtowcは内部でmbstate_tを利用しているので、mbrtowcを利用しないとスレッドセーフにはならないですね。
            親コメント
    • でかい (スコア:2, 参考になる)

      by Kanji (8729) <h-gomiNO@SPAMmanuke.com> on 2002年07月23日 9時50分 (#131240) ホームページ 日記
      パッチでどれだけ肥大したかというとそんなに大きくなっていなさそうに思います。憶測ですが。

      このまえ 1FD Linux 作成キット [rim.or.jp] を使ってフロッピー1枚のシステムを作ろうとしたのですが、bash が 400KB くらいあるのを見てびっくりしました。普通の sh なら 30-60KB くらいだった覚えがあります。どのへんにコードを使っているのでしょう。

      最近のディストリビューションの rc.d 内のスクリプトは、sh -> bash ではなく素の sh を使うと動いてくれないものがあったのにも驚きました。sh にもバージョンがあるのでしょうか。動かない以上、#!/bin/sh なんて書いて欲しくありません。
      親コメント
      • Re:でかい (スコア:3, 参考になる)

        by aonoto (9756) on 2002年07月23日 11時01分 (#131296)
        最近のディストリビューションの rc.d 内のスクリプトは、sh -> bash ではなく素の sh を使うと動いてくれないものがあったのにも驚きました。sh にもバージョンがあるのでしょうか。動かない以上、#!/bin/sh なんて書いて欲しくありません。

        bashは素のBourne Shellより拡張されていますのでbash前提のLinuxならそういうスクリプトもありなのでしょう。ちょっと例が違いますが、GNU Autoconf, Automake and Libtool [redhat.com](オーム社から 刊行されているやつの原書)中で ポータブルなBourne Shellスクリプトを書くには [redhat.com]、という節があります。

        #どれが「素のBourne Shell」や、という突っ込みが来そう(^^;

        親コメント
      • by tietew (6130) on 2002年07月23日 11時04分 (#131299) ホームページ
        というか,[ $foo == bar ] とか素で書いてしまうので sh で動かないものが出来上がるんでしょうなあ。
        普段 bash を使っていると気づかないんですよね。
        あと,どの機能が bash 拡張なのか微妙に判りづらいってことも。
        # 言い訳だけどさっ!
        親コメント
      • bashがshよりスクリプトを書くのが便利だっていうのはよくわかるんですが、bashで起動スクリプトを書くのはやめてほしいものです。
        格納できる場所が少ないとか、メモリが少ないとかいう人間にはちょっときつめ。
        まあ、shで書き直して切り抜けられるといえばそうですが。

        bashくらい多機能になるともう、インタラクティブシェルに特化させたほうがよいのではという気にもなってきます。
        起動スクリプトに多機能を求めるなら、どうせならもっと使いやすい別のスクリプト言語を開発するとか。
        まあ、水掛け論だし、128MBのメモリいくらで売ってる?といわれれば返す言葉もありませんが。

        #でもわしのメインマシンは486SX 12Mz 6MBメモリーなんだよな。
        #代替機ないし。
        --
        ------------------------- Excess and Obsolete
        親コメント
      • bashism (スコア:1, 参考になる)

        by kubota (64) on 2002年07月23日 13時46分 (#131442) ホームページ 日記
        最近のディストリビューションの rc.d 内のスクリプトは、sh -> bash ではなく素の sh を使うと動いてくれないものがあったのにも驚きました。sh にもバージョンがあるのでしょうか。動かない以上、#!/bin/sh なんて書いて欲しくありません。
        Debian の場合は、それは (bashism と呼ばれる) バグとみなされますのでバグ報告をください。Debian ポリシーで規定されていること [debian.or.jp]への違反になるので、けっこう重大なバグです (が、たびたび報告されています)。

        ほかでも、たぶん同様の考え方だと推測しますが、どうでしょうか。

        親コメント
    • by SteppingWind (2654) on 2002年07月23日 19時22分 (#131647)

      問題点はスクリプトインタープリタとコマンドラインユーザインターフェイスを一つのプログラムで兼用しちゃっているところに有るんでしょうね.

      私は古い人間なので, 前者にはsh後者にはcshという使い分けをしていて, それが現在のashとtcshの環境にそのまま引き継がれているわけですが. X68000とかでbashを使っていたころは, 確かに軽かったですね.

      親コメント
    • by Anonymous Coward
      とっても使いたいです…てゆうかばりばり使ってますが。
      # EUC-JP と Shift_JIS が混在するとどう振る舞うんだろう (^^;;
      • by kubota (64) on 2002年07月23日 8時37分 (#131197) ホームページ 日記
        「混在」というのが、よくわからないんですが、

        ja_JP.SJIS ロケールでは、いわゆる半角カナも含めて、 Shift_JIS を正しく扱います。

        ただし、ふつうは ja_JP.SJIS ロケールなんてのが用意されてない だろうから、localedef コマンドを使って作らないといけません。

        親コメント
        • あれ? ja_JP.SJISちゃんと動きますか?
          bash-2.05b$ echo 表表
          とかすると、2byte目の0x5cが悪さするんですが。
          --
          Just a whisper. I hear it in my ghost.
          親コメント
        • ja_JP.SJIS ロケールは,作成可能でしょうか。

          最近流行の,Shift_JIS を厳密に解釈することを求める立場からすると, 0x5C のコードポイントにある文字 (\) は,Shift_JIS ではバックスラッシュ (REVERSE SOLIDUS) ではなくて円記号 (YEN SIGN) です。 そして,ISO C にしろ,POSIX にしろ,バックスラッシュのコードポイントがロケールによって動的に変わってしまう状況は想定していないはずなので, たとえ charmap ファイルは作成可能にしても, それを実際に運用するのは難しいと思います。

          たとえば,0x5C の文字は Shift_JIS では円記号だからエスケープ文字ではないはずなのに,プログラムによってエスケープ文字と解釈されたり(しなかったり)するとか。もっとも
          LANG=ja_JP.SJIS; export LANG
          とかやったとたんに,既存のシェルスクリプトが軒並み動かなくなったりするのも困りますけどね :)

          いや,もちろん,堅いことを言わなければ使えるのはわかりますよ。

          親コメント
          • CP932 (スコア:2, 興味深い)

            by kubota (64) on 2002年07月23日 15時02分 (#131502) ホームページ 日記
            既存のシステムでこの問題をてっとりばやく片付ける方法は、Shift_JIS の代わりに CP932 を使うことです。

            CP932 は、日本語版 Windows で使われている文字コードで、(JIS X 02xx の世界から見れば) Shift_JIS にいわゆる「機種依存文字」を追加したものです。が、ミソは、Unicode から見たとき、Shift_JIS と CP932 はそれ以上の差異があるという点です。

            それは、CP932 と Shift_JIS とでは、Unicode への変換テーブルに一部相違がある、という点です。そのひとつの例として、CP932 では、0x5c は U+005C に変換されます。ほか、JIS X 0208 に属する文字にも、いくつか相違があります。

            問題は、日本語版 Windows では、U+005C は円記号だったりすることなんだけど、いまのところそれは関係ないし。

            親コメント
  • bash on Windows (スコア:2, 参考になる)

    by rug (55) on 2002年07月23日 10時06分 (#131251) 日記
    Cygwinだとlocale回りがまんまnewlib [redhat.com]であってないようなものなので(一応i18nパッチ [jaist.ac.jp]は存在しますが)、multibyte supportの恩恵を受けられないという罠。MicrosoftのC runtimeにはワイド文字用の関数がありますが、Win 9x系だと機能しないような。あ、それ以前にbash2ってNative Win32でbuildできたっけ? (^^;;
  • bashに日本語を入力するもしくはファイル作成ことってそんなに多くない気がするのですが?自分の環境では、KDEが使っている「ごみ箱」しか無いのですが…
    普通は、Xを立ち上げて日本語を入力しますが、その場合代替手段ありますし、コンソール上でも日本語表示できませんからね(konやjfbterm使えば良いけどね)。あ、grepか。シェルスクリプトを書く場合が一番活躍しそうですね。perl何かを使うまでもないときや

    今回の場合、あまり使用頻度は高くないけれども、とりあえず対応しておかなければまずいだろうという感じなのですかね。なくて困ることがあってもあって困ることはないというふうに
    バージョンからもそれほど重要視していないようですし。(大きな変化だと告げたい場合2.1等になるでしょうから)

    あと以外とbusyboxのashが良い感じですよ。大きさ・機能ともに。viも正式に対応して欲しいかも
    --
    うすっぺらいコメントがあらわれた! ▼
    • by ueno-t (3169) on 2002年07月23日 10時56分 (#131290)
      > bashに日本語を入力するもしくはファイル作成ことってそんなに多くない気がするのですが?

      僕としては、ファイル名が日本語のMP3を検索出来るようになったのがありがたいです。mpg123に直接ぶちこめますし。
      ただ、今までもbashで問題なく日本語ファイル名の補完は効いてたような気がするんですが。

      親コメント
      • Re:底辺拡大 (スコア:2, おもしろおかしい)

        by tietew (6130) on 2002年07月23日 11時12分 (#131304) ホームページ
        アアア.mp3 と アアイ.mp3 を「ア」から補完すると アア<0xA5> まで補完されてしまうので,混乱する罠。
        親コメント
      • Re:底辺拡大 (スコア:2, 参考になる)

        by Anonymous Coward on 2002年07月23日 11時27分 (#131313)
        タレコミは readline のみにフォーカスしているようですが、
        globbing などの部分にも国際化が施されているようで、
        「?」などが「一文字」にマッチするようです。
        #まぁ、ファイルのエンコーディングと 実行ロケールが
        #あってないと正しく動作しませんが
        親コメント
        • Re:底辺拡大 (スコア:1, おもしろおかしい)

          by Anonymous Coward on 2002年07月23日 11時38分 (#131322)
          お!ほんとだ

          $ ls
          巨乳 爆乳 美乳 貧乳 麗乳
          $ ls [美麗]乳
          美乳 麗乳
          親コメント
          • Re:底辺拡大 (スコア:2, おもしろおかしい)

            by Anonymous Coward on 2002年07月23日 15時10分 (#131505)
            やっぱ性器表現っしょ
            % grep '[まち]んこ' foo
            みたいな

            # "うんこ" は match しません :-P
            親コメント
  • bashではなく (スコア:1, 興味深い)

    by Anonymous Coward on 2002年07月23日 23時36分 (#131810)
    tcshの話題でスマンが、面白いもの [freebsd.org]を見つけたので紹介します。

    これなら日本語ファイル名を扱うのも楽になるかも。
  • 拍手 (スコア:0, 余計なもの)

    by Anonymous Coward on 2002年07月23日 4時52分 (#131149)
    拍手
typodupeerror

物事のやり方は一つではない -- Perlな人

読み込み中...