アカウント名:
パスワード:
ちなみに、HANDLE_MULTIBYTE を見付けるためにソースを漁っている 最中に、mbstate_t が多数使われていることにも気付きました。 おそらく、stateful なエンコーディング (ISO-2022-JP など) にも対応しているのではないかと思います。 (使う人は、いるのかなあ)
ちなみに、ぼくはメモリ 12MB のマシンを持っていますが、 bash が重いと思ったことはありませんが、 さすがに emacs は重いと思いました。
軽いシェルですが、NetBSD の sh (Debian では ash という名前でパッケージングされています) は、 POSIX シェルです (#!/bin/sh として使える) が、 非常に軽いですよ。そのかわり、機能がかなり制限されますが。
最近のディストリビューションの 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」や、という突っ込みが来そう(^^;
ほかでも、たぶん同様の考え方だと推測しますが、どうでしょうか。
#!/bin/sh なんて書いて欲しくありません。
問題点はスクリプトインタープリタとコマンドラインユーザインターフェイスを一つのプログラムで兼用しちゃっているところに有るんでしょうね.
私は古い人間なので, 前者にはsh後者にはcshという使い分けをしていて, それが現在のashとtcshの環境にそのまま引き継がれているわけですが. X68000とかでbashを使っていたころは, 確かに軽かったですね.
ja_JP.SJIS ロケールでは、いわゆる半角カナも含めて、 Shift_JIS を正しく扱います。
ただし、ふつうは ja_JP.SJIS ロケールなんてのが用意されてない だろうから、localedef コマンドを使って作らないといけません。
$ ls /usr/lib/locale/ de_DE en_US.utf8 fr_FR@euro ja_JP.sjis ko_KR.euckr en_US fr_FR ja_JP.eucjp ja_JP.utf8 ru_RU.koi8r $ echo $LANG ja_JP.SJIS $ echo 表表 表表 $ echo 表表 | od -t x1 0000000 95 5c 95 5c 0a 0000005 $
ヒストリとか、カーソル移動とか、編集も問題ありません。
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 は、日本語版 Windows で使われている文字コードで、(JIS X 02xx の世界から見れば) Shift_JIS にいわゆる「機種依存文字」を追加したものです。が、ミソは、Unicode から見たとき、Shift_JIS と CP932 はそれ以上の差異があるという点です。
それは、CP932 と Shift_JIS とでは、Unicode への変換テーブルに一部相違がある、という点です。そのひとつの例として、CP932 では、0x5c は U+005C に変換されます。ほか、JIS X 0208 に属する文字にも、いくつか相違があります。
問題は、日本語版 Windows では、U+005C は円記号だったりすることなんだけど、いまのところそれは関係ないし。
一方で、伝統的な ja_JP.SJIS では、JIS X 0201 Roman は ISO 646 の思想に従って \ を ISO 646-IRV のそれと同質に 解釈するのが普通だったりしますな。
苦し紛れにそういうことをしていたのは事実ですが, それは「ISO 646 の思想」というほど 確乎としたものなのでしょうか。 ISO 646 は ASCII をもとにした符号化文字集合で, 「各国版 (National version)」として一部の文字を入れ替えた版を作ることを許してはいましたが, そのうちの入れ替えられた文字を別の National version の文字 あるいは「国際参照版 (IRV)」と同等に解釈してよいという規定はなかったと思います。
たとえば,日本版では 0x5C は「円記号」ですが, 韓国版ではこれは「ウォン記号」になります。 これを一緒にされたら困るでしょう。 貨幣価値も一桁くらい違うし :-)
ファイルシステムにファイル名を書き込むなら、そのファイルシステムでサポートするコーディングで格納するべきで、ロケール設定に従うのはちょっと変かなと思う。
これはこれで納得できる考え方ではあります。普通に現実的解法を求めるなら、ほとんど必然的結論とすら言えるかもしれません。
とはいえ、UNIXといえば昔から、カーネル内ではなるべくテキスト表現の方法に依存せず、単なるバイト列として生のまま処理しようとするところに特徴があったという考えもできます。例えばファイルの中身はある長さを持つバイト列というだけあって、カーネルはそれが「80文字レコード」だの「可変長文字レコード」だのといった構造を持っているかどうかは関知しません。UnixやWindowsなどはその点で同じ特徴を持っていますが、そうでないOSもあります。UnixとWindowsでは改行文字が違うと言われることもありますが、それはOSが何か改行文字を特別扱いしているというわけではなくて、それぞれのアプリケーションが特定のバイト列をどう改行と見なすかというだけの違いで、実はアプリケーション毎に異なった扱いでも(OSから見れば)構いません(少なくともUnixでは。Windowsではもしかすると特別扱いがあるのかもしれませんが、寡聞にして知りません)。
ファイル名にしても同様で、伝統的Unixではディレクトリ中のファイル名は(必要ならNULで終端した)14バイト以内(その後もっと長くできるよう拡張された)の列と決まっていただけでした。ファイルシステム自体は、NULだけは特殊な意味を持っていたものの、あとは長さの制限だけしか持っておらず、それを守る限りは、アプリケーションが、ファイル名自身バイナリ列であるようなファイルを使っても、OSは気にしません(ただしカーネル内のnamei()関数が"/"を特別扱いするために、NULに加えて"/"も特別扱いになっています。これは、個人的にはUnixの齟齬の一つと思います)。
しかしファイルシステムにlocaleを持ち込んでしまうと、アプリケーションの指定したファイル名というバイト列が、暗黙の内に別のバイト列に変換されてしまうわけで、これはせっかくの「単なるバイト列」という特徴を崩してしまう気がします。極端な話アプリケーションがファイル名自体がバイナリであるようなファイルを作る場合、あるlocaleの下では同一ではあっても、バイト列としては異なるファイル名に変換されてしまい、アプリケーションが不具合を起こすということもあるでしょう。(まあ、そんな変なファイル名をつける方が悪いというのは常識的には正しい指摘なのですが。)
そういったわけで、私の個人的感情としては、Unixカーネルはあくまですべてを単なるバイト列として扱い、そこにテキスト表現を見いだすのはアプリケーションレベル以上だけにして欲しい、という気持ちがあります。カーネルはあくまでシンプルに、完全に予測可能な動作だけをするべし……。
とはいえ、それでは実在のUnixは完全にテキスト表現から完全に独立だったかと言うと、まあ"/"の例もあるように、実際にはそうではないわけで。いわばUnixは「ASCIIとその拡張文字集合およびASCIIと矛盾しない文字符号系」を暗黙に仮定していたとも言えます。だとすると、この暗黙の制限を、より強く明示的にして、その強い制限の下ですべてのアプリケーションを書くことにするのも、Unixの延長としてはあながち不自然ではないのかもしれません。そういう意味では、例えば元コメントのように、
> UTF-8とかで、NULLと/を含まない文字列を許す
とかはアリなのかもしれません。これならば、アプリケーションがUTF-8として作ったファイル名というバイト列を、カーネルはそのままファイルシステムに格納すれば良いだけだからです。これがUnix的思想の自然な拡張として有り得る形であるという 証拠に、元々のUnix開発者がその後開発した(している)Plan9では、ファイルシステムはunicodeで統一されていると聞いています。(それにしても「何もunicodeでなくてもいいじゃないかぁ!」というanti-unicode派としての叫びはおいておいて……)
何が言いたかったかと言うと、カーネルは暗黙の文字変換なんてせずに、あくまでアプリケーションの言うがままのバイト列を生のまま扱うことに徹するべきだと私は思う、ということです。そのためには、アプリケーションが(localeなどの)それぞれの解釈でファイルシステムを見るのは、別におかしなことではないが、それが嫌ならすべてのアプリケーションが(unicodeなどの)同一の解釈でファイルシステムを見ることに決めてしまっても良い、と。
もっとも、ドラスティックな変更を避け、簡便に使うという目的にあっては、ファイルシステム自体がlocaleを持つという仕組みを否定するものではありません。また、最後ついでに言うと、Plan9みたいに統一するにしてもunicode
ただ、ファイルシステムにファイル名を書き込むなら、そのファイルシステムでサポートするコーディングで格納するべきで、ロケール設定に従うのはちょっと変かなと思う。
Windows NT/NTFS とかだと, ディスクに格納されるファイル名は Unicode で, かつプロセスが非 Unicode エンコーディングを使う場合に何を使うかという情報がプロセスの属性としてあるので,ファイル操作システムコールでファイル名としてどの文字エンコーディングが渡されるかが判定できます。それに対して UNIX の場合,「プロセスがファイル名文字列をどの文字エンコーディングで渡してくるか」という情報をカーネルレベルでもっていないので,変換しようにもできない。 (ロケール処理はライブラリレベルで実現されていて, カーネルレベルでは認識されていないので。)
NFS とか FAT ファイルシステムとかのマウントのときに, 文字エンコーディングを指定できるようにした処理系もありますが, これは,どちらかといえば苦し紛れの策ですからね。
タレコミと矛盾してるかもしれませんが、ぼくは、現時点ではまだ日本語ファイル名は使わないほうがいいと思っています。ひとつの理由は、違うエンコーディングを使いたいときにファイル名は変更すべきなのかどうなのかが不明だということです。EUC-JP と Unicode の変換テーブルにも「ばらつき」がありますし。
8 ビット言語圏では、そういうことは何も考えずに非 ASCII 文字を使ってしまっている場合が多そうです。が、かれらもやがて同様の問題を抱えるはずです。
もし将来、UTF-8 が主流になり、さらに、UTF-8 以外を使うことはほとんど考えられない、という状況になれば (いまでいう ASCII と EBCDIC の関係みたいなもの?)、日本語ファイル名を使っても問題が起きないだろうと思いますが。
同じ問題を IDN が抱えてたりしますが、IDN は一応正規化ルールが あって、混乱がある程度抑えられるように考えられてますな。
IDN (Internationalized Domain Name) でそういう話が 出ているのは聞いているのですが, 同じ話は IRI (Internationalized Resource Identifier) でも出てきますよね。 つまり,URI として “http://ドメイン名/パス名” というのがあったときに,「ドメイン名」の部分は IDN のルールが適用されるのですが, 「パス名」の部分は IRI のルールが適用されるわけで, それらが矛盾しているとかなり困りますが。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
身近な人の偉大さは半減する -- あるアレゲ人
重い (スコア:3, 興味深い)
そんなに多バイト文字つかいたいんですか?
まあ、メモリ一桁メガバイトの住人のたわごとか。
------------------------- Excess and Obsolete
軽いシェル (スコア:4, 参考になる)
ちなみに、HANDLE_MULTIBYTE を見付けるためにソースを漁っている 最中に、mbstate_t が多数使われていることにも気付きました。 おそらく、stateful なエンコーディング (ISO-2022-JP など) にも対応しているのではないかと思います。 (使う人は、いるのかなあ)
ちなみに、ぼくはメモリ 12MB のマシンを持っていますが、 bash が重いと思ったことはありませんが、 さすがに emacs は重いと思いました。
軽いシェルですが、NetBSD の sh (Debian では ash という名前でパッケージングされています) は、 POSIX シェルです (#!/bin/sh として使える) が、 非常に軽いですよ。そのかわり、機能がかなり制限されますが。
Re:軽いシェル (スコア:2, 参考になる)
ash は POSIX/SUSv3 には準拠していないが、 FreeBSD の /bin/sh は FreeBSD C99 & POSIX Conformance Project [freebsd.org] で準拠のための作業が進行中。NetBSD とFreeBSD では変更を相互にマージしている。
POSIX には不備やほとんど無意味な規定もあるから完全準拠の是非は微妙だが、可能な範囲で擦り寄ることは大事、かな。
stateful なエンコーディング (スコア:2, 興味深い)
>に、mbstate_t が多数使われていることにも気付きました。 おそらく、
>stateful なエンコーディング (ISO-2022-JP など) にも対応しているので
>はないかと思います。 (使う人は、いるのかなあ)
Linux上の話に限定してしまえば、bashがstatefulなエンコーディングをサポートしていようがいまいがglibcがそもそもstatefulなエンコーディングをサポートしていないはずなので関係ないと思います。が、世の中にはLinux以外のOSも数多く存在してますので、使う人もいると思います。
今は亡きKondaraにおいてこのパッチを採用した際に、パフォーマンスが劇的に悪くなった、と文句しこたまいわれたりしたので、1バイトで事足りるようなロカールの場合にはマルチバイト文字ワイド文字の変換をスキップするようにした(他にword wrapやいくつかのバグつぶし)パッチをIBMの方に送付したのですが、この時に「mbstate_tを初期化してないためにstatefulなエンコーディングで正常に動作しません。」と注意された記憶があります。
Re:stateful なエンコーディング (スコア:1, 参考になる)
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) {
エラー処理 /* ワイド文字に変換できなかった */
}
}
.
.
. ワイド文字を使った処理
.
.
# ほかにも,スレッドセーフにしたいときなどが考えられます。
Re:stateful なエンコーディング (スコア:1)
あ、すみません。もちろん最初にシフト状態は初期化しないといけません。私の送ったパッチはそこにバグをいれてしまっていたのですが、statelessなエンコーディングを利用している場合、すくすく動作してしまっていたので...。
IBMの作成していた国際化部分では、mbrtowcの戻り値のチェックはそれほど厳密にやっていません。-1の場合も-2の場合も同様のものとして扱っています。
僕が知る範囲では、mbrtowcをまっとうに利用しているアプリケーションは非常に少ないですね。IBMが作成しているパッチでは、全てmbrtowcを利用するようになっていて、企業としてのポリシーを感じます。
> # ほかにも,スレッドセーフにしたいときなどが考えられます。
少なくともglibcの実装では、mbtowcは内部でmbstate_tを利用しているので、mbrtowcを利用しないとスレッドセーフにはならないですね。
Re:stateful なエンコーディング (スコア:0)
input.c とかを覗くとやってるみたいに見える。
Re:stateful なエンコーディング (スコア:0)
Re:stateful なエンコーディング (スコア:0)
2.04 の patch もあったと思うけど、もうないのかな?
Re:stateful なエンコーディング (スコア:0)
再開始可能な関数を使ったほうがいいです。
glibcを例にとりますと,glibcはmbswcs系関数で関数内で処理をする際,
mbstate_tに変換途中の情報を入れてます。
だから,mbtowcは,スレッドセーフになってないわけです。
(コメントから察するにこの辺のことはご存知だと思われますが。)
では,mbtowcでエラーが返ったとき,内部に持っているmbstate_tはどうなるでしょう?
添付のコードを試されると判ります。
といっても ja_JP.SJISロケール向けハードコードですので(すいません),
結果をばここに。
$ ./mb
Re:stateful なエンコーディング (スコア:0)
でも,「手元で状態を把握していたほうがいい。」っていうことを示したいなら,
EUC の Single Shift を例にしたほうがいいかと。
それなら別に glibc に依存しないし。
でかい (スコア:2, 参考になる)
このまえ 1FD Linux 作成キット [rim.or.jp] を使ってフロッピー1枚のシステムを作ろうとしたのですが、bash が 400KB くらいあるのを見てびっくりしました。普通の sh なら 30-60KB くらいだった覚えがあります。どのへんにコードを使っているのでしょう。
最近のディストリビューションの rc.d 内のスクリプトは、sh -> bash ではなく素の sh を使うと動いてくれないものがあったのにも驚きました。sh にもバージョンがあるのでしょうか。動かない以上、#!/bin/sh なんて書いて欲しくありません。
Re:でかい (スコア:3, 参考になる)
bashは素のBourne Shellより拡張されていますのでbash前提のLinuxならそういうスクリプトもありなのでしょう。ちょっと例が違いますが、GNU Autoconf, Automake and Libtool [redhat.com](オーム社から 刊行されているやつの原書)中で ポータブルなBourne Shellスクリプトを書くには [redhat.com]、という節があります。
#どれが「素のBourne Shell」や、という突っ込みが来そう(^^;
Re:でかい (スコア:1)
普段 bash を使っていると気づかないんですよね。
あと,どの機能が bash 拡張なのか微妙に判りづらいってことも。
# 言い訳だけどさっ!
Re:でかい (スコア:1)
格納できる場所が少ないとか、メモリが少ないとかいう人間にはちょっときつめ。
まあ、shで書き直して切り抜けられるといえばそうですが。
bashくらい多機能になるともう、インタラクティブシェルに特化させたほうがよいのではという気にもなってきます。
起動スクリプトに多機能を求めるなら、どうせならもっと使いやすい別のスクリプト言語を開発するとか。
まあ、水掛け論だし、128MBのメモリいくらで売ってる?といわれれば返す言葉もありませんが。
#でもわしのメインマシンは486SX 12Mz 6MBメモリーなんだよな。
#代替機ないし。
------------------------- Excess and Obsolete
bashism (スコア:1, 参考になる)
ほかでも、たぶん同様の考え方だと推測しますが、どうでしょうか。
Re:bashism (スコア:0)
Re:でかい (スコア:0)
シェルの位置づけ (スコア:1)
問題点はスクリプトインタープリタとコマンドラインユーザインターフェイスを一つのプログラムで兼用しちゃっているところに有るんでしょうね.
私は古い人間なので, 前者にはsh後者にはcshという使い分けをしていて, それが現在のashとtcshの環境にそのまま引き継がれているわけですが. X68000とかでbashを使っていたころは, 確かに軽かったですね.
Re:重い (スコア:0)
# EUC-JP と Shift_JIS が混在するとどう振る舞うんだろう (^^;;
EUC-JP と Shift_JIS が混在 (スコア:2, 参考になる)
ja_JP.SJIS ロケールでは、いわゆる半角カナも含めて、 Shift_JIS を正しく扱います。
ただし、ふつうは ja_JP.SJIS ロケールなんてのが用意されてない だろうから、localedef コマンドを使って作らないといけません。
Re:EUC-JP と Shift_JIS が混在 (スコア:1)
bash-2.05b$ echo 表表
とかすると、2byte目の0x5cが悪さするんですが。
Just a whisper. I hear it in my ghost.
Re:EUC-JP と Shift_JIS が混在 (スコア:1)
$ ls /usr/lib/locale/
de_DE en_US.utf8 fr_FR@euro ja_JP.sjis ko_KR.euckr
en_US fr_FR ja_JP.eucjp ja_JP.utf8 ru_RU.koi8r
$ echo $LANG
ja_JP.SJIS
$ echo 表表
表表
$ echo 表表 | od -t x1
0000000 95 5c 95 5c 0a
0000005
$
ヒストリとか、カーソル移動とか、編集も問題ありません。
Re:EUC-JP と Shift_JIS が混在 (スコア:0)
$ export LANG=ja_JP.SJIS
$ bash
$ echo 表表
表表
$ echo 噂
噂
$
Re:EUC-JP と Shift_JIS が混在 (スコア:1)
/usr/lib/nls/loc/ あたりを修正しないと動かないのかな。
Just a whisper. I hear it in my ghost.
Re:EUC-JP と Shift_JIS が混在 (スコア:1)
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, 興味深い)
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 は円記号だったりすることなんだけど、いまのところそれは関係ないし。
Re:CP932 (スコア:0)
> 最近流行の,Shift_JIS を厳密に解釈することを求める立場
の人に
> 既存のシステムでこの問題をてっとりばやく片付ける方法は、Shift_JIS の代わりに CP932 を使うことです。
というのは、返答としてどうかな?と思います。
それはともかく、Single Unix Specification の該当項 [opengroup.org]を読んでみましたが、
Escape Character って確かに Bac
Re:EUC-JP と Shift_JIS が混在 (スコア:0)
Unicode が絡むとまともに処理するのが難しいものの、
それをちゃんと解決できないのは実装がヘボイだけ、
というそしりを免れるものではありません。
Re:EUC-JP と Shift_JIS が混在 (スコア:1)
とか書いたんですけど、よくよく考えてみるとそんな単純な
話でもないのかなぁ、と思い始めたりして。
どうもこの辺は実装依存の話で、Single Unix Spec あたりを見ても
厳密には書いてないのですけど、Portable charset としては確かに、
\ として reverse solidus とか backslash とか書いてあるんですよね。
一方で、伝統的な ja_JP.SJIS では、JIS X 0201 Roman は
ISO 646 の思想に従って \ を ISO 646-IRV のそれと同質に
解釈するのが普通だったりしますな。
結局、そこは実装依存という話なので、一概に言い切れない、
という話ですね。失礼しました。
Re:EUC-JP と Shift_JIS が混在 (スコア:1)
苦し紛れにそういうことをしていたのは事実ですが, それは「ISO 646 の思想」というほど 確乎としたものなのでしょうか。 ISO 646 は ASCII をもとにした符号化文字集合で, 「各国版 (National version)」として一部の文字を入れ替えた版を作ることを許してはいましたが, そのうちの入れ替えられた文字を別の National version の文字 あるいは「国際参照版 (IRV)」と同等に解釈してよいという規定はなかったと思います。
たとえば,日本版では 0x5C は「円記号」ですが, 韓国版ではこれは「ウォン記号」になります。 これを一緒にされたら困るでしょう。 貨幣価値も一桁くらい違うし :-)
Re:EUC-JP と Shift_JIS が混在 (スコア:0)
Re:重い (スコア:0)
Re:重い (スコア:1, すばらしい洞察)
所詮 filename は NULL と / を含まない バイト列。
どっかで紳士協定が無いとね…
Re:重い (スコア:1)
ただ、ファイルシステムにファイル名を書き込むなら、そのファイルシステムでサポートするコーディングで格納するべきで、ロケール設定に従うのはちょっと変かなと思う。
実際は、"UTF-8とかで、NULLと/を含まない文字列を許す(制御文字はダメだけど)"ほうが現実的ですよね。(問題起こしにくいですよね)
# 当たり前なのかな
# 変なこと言ってる?
M-FalconSky (暑いか寒い)
カーネルの基本は「無変換」であるべし教 :-) (スコア:3, 興味深い)
これはこれで納得できる考え方ではあります。普通に現実的解法を求めるなら、ほとんど必然的結論とすら言えるかもしれません。
とはいえ、UNIXといえば昔から、カーネル内ではなるべくテキスト表現の方法に依存せず、単なるバイト列として生のまま処理しようとするところに特徴があったという考えもできます。例えばファイルの中身はある長さを持つバイト列というだけあって、カーネルはそれが「80文字レコード」だの「可変長文字レコード」だのといった構造を持っているかどうかは関知しません。UnixやWindowsなどはその点で同じ特徴を持っていますが、そうでないOSもあります。UnixとWindowsでは改行文字が違うと言われることもありますが、それはOSが何か改行文字を特別扱いしているというわけではなくて、それぞれのアプリケーションが特定のバイト列をどう改行と見なすかというだけの違いで、実はアプリケーション毎に異なった扱いでも(OSから見れば)構いません(少なくともUnixでは。Windowsではもしかすると特別扱いがあるのかもしれませんが、寡聞にして知りません)。
ファイル名にしても同様で、伝統的Unixではディレクトリ中のファイル名は(必要ならNULで終端した)14バイト以内(その後もっと長くできるよう拡張された)の列と決まっていただけでした。ファイルシステム自体は、NULだけは特殊な意味を持っていたものの、あとは長さの制限だけしか持っておらず、それを守る限りは、アプリケーションが、ファイル名自身バイナリ列であるようなファイルを使っても、OSは気にしません(ただしカーネル内のnamei()関数が"/"を特別扱いするために、NULに加えて"/"も特別扱いになっています。これは、個人的にはUnixの齟齬の一つと思います)。
しかしファイルシステムにlocaleを持ち込んでしまうと、アプリケーションの指定したファイル名というバイト列が、暗黙の内に別のバイト列に変換されてしまうわけで、これはせっかくの「単なるバイト列」という特徴を崩してしまう気がします。極端な話アプリケーションがファイル名自体がバイナリであるようなファイルを作る場合、あるlocaleの下では同一ではあっても、バイト列としては異なるファイル名に変換されてしまい、アプリケーションが不具合を起こすということもあるでしょう。(まあ、そんな変なファイル名をつける方が悪いというのは常識的には正しい指摘なのですが。)
そういったわけで、私の個人的感情としては、Unixカーネルはあくまですべてを単なるバイト列として扱い、そこにテキスト表現を見いだすのはアプリケーションレベル以上だけにして欲しい、という気持ちがあります。カーネルはあくまでシンプルに、完全に予測可能な動作だけをするべし……。
とはいえ、それでは実在のUnixは完全にテキスト表現から完全に独立だったかと言うと、まあ"/"の例もあるように、実際にはそうではないわけで。いわばUnixは「ASCIIとその拡張文字集合およびASCIIと矛盾しない文字符号系」を暗黙に仮定していたとも言えます。だとすると、この暗黙の制限を、より強く明示的にして、その強い制限の下ですべてのアプリケーションを書くことにするのも、Unixの延長としてはあながち不自然ではないのかもしれません。そういう意味では、例えば元コメントのように、
とかはアリなのかもしれません。これならば、アプリケーションがUTF-8として作ったファイル名というバイト列を、カーネルはそのままファイルシステムに格納すれば良いだけだからです。これがUnix的思想の自然な拡張として有り得る形であるという 証拠に、元々のUnix開発者がその後開発した(している)Plan9では、ファイルシステムはunicodeで統一されていると聞いています。(それにしても「何もunicodeでなくてもいいじゃないかぁ!」というanti-unicode派としての叫びはおいておいて……)
何が言いたかったかと言うと、カーネルは暗黙の文字変換なんてせずに、あくまでアプリケーションの言うがままのバイト列を生のまま扱うことに徹するべきだと私は思う、ということです。そのためには、アプリケーションが(localeなどの)それぞれの解釈でファイルシステムを見るのは、別におかしなことではないが、それが嫌ならすべてのアプリケーションが(unicodeなどの)同一の解釈でファイルシステムを見ることに決めてしまっても良い、と。
もっとも、ドラスティックな変更を避け、簡便に使うという目的にあっては、ファイルシステム自体がlocaleを持つという仕組みを否定するものではありません。また、最後ついでに言うと、Plan9みたいに統一するにしてもunicode
Re:重い (スコア:2, 参考になる)
Windows NT/NTFS とかだと, ディスクに格納されるファイル名は Unicode で, かつプロセスが非 Unicode エンコーディングを使う場合に何を使うかという情報がプロセスの属性としてあるので,ファイル操作システムコールでファイル名としてどの文字エンコーディングが渡されるかが判定できます。それに対して UNIX の場合,「プロセスがファイル名文字列をどの文字エンコーディングで渡してくるか」という情報をカーネルレベルでもっていないので,変換しようにもできない。 (ロケール処理はライブラリレベルで実現されていて, カーネルレベルでは認識されていないので。)
NFS とか FAT ファイルシステムとかのマウントのときに, 文字エンコーディングを指定できるようにした処理系もありますが, これは,どちらかといえば苦し紛れの策ですからね。
Re:重い (スコア:0)
つか、Linux だと root のデフォルトもそれになるのだな。
ウーム
まぁ FreeBSD もデフォルト /bin/tcsh の時代ですし...
Re:重い (スコア:0)
まあ 私の使ってない機能が山ほどある、ということですね。
Re:重い (スコア:0)
UTF-8 だと ASCII 以外は全て多バイト文字なんです。
つまり、CJK 住人でなくとも今後必要なんです。
#日本人の人達はファイル名等に ASCII しか使わないというのが
#しみついてるかもしれせんが ;-)
多言語ファイル名 (スコア:2, 興味深い)
タレコミと矛盾してるかもしれませんが、ぼくは、現時点ではまだ日本語ファイル名は使わないほうがいいと思っています。ひとつの理由は、違うエンコーディングを使いたいときにファイル名は変更すべきなのかどうなのかが不明だということです。EUC-JP と Unicode の変換テーブルにも「ばらつき」がありますし。
8 ビット言語圏では、そういうことは何も考えずに非 ASCII 文字を使ってしまっている場合が多そうです。が、かれらもやがて同様の問題を抱えるはずです。
もし将来、UTF-8 が主流になり、さらに、UTF-8 以外を使うことはほとんど考えられない、という状況になれば (いまでいう ASCII と EBCDIC の関係みたいなもの?)、日本語ファイル名を使っても問題が起きないだろうと思いますが。
Re:多言語ファイル名 (スコア:2, 興味深い)
KDEでは環境変数経由とは言え、ファイル名にUTF8を使うかlocale codingを使うかを選択できるように [kde.org]なっています。
(ファイル名を変換するツールもあったはず)
たしかGNOME2も同様の機能があったと記憶しているのですが、
ポインターを見つけられませんでした。
-- Che Che - Bye Bye
Re:多言語ファイル名 (スコア:1, 参考になる)
G_BROKEN_FILENAMES
という環境変数がセットされているかどうかを見て
g_filename_to_utf8()
の処理が変わります。
Re:多言語ファイル名 (スコア:0)
あって、混乱がある程度抑えられるように考えられてますな。
ファイル名もあれと同じくらい厳密(といってもまだ不十分だけど)に
処理しないと混乱が
Re:多言語ファイル名 (スコア:1)
IDN (Internationalized Domain Name) でそういう話が 出ているのは聞いているのですが, 同じ話は IRI (Internationalized Resource Identifier) でも出てきますよね。 つまり,URI として “http://ドメイン名/パス名” というのがあったときに,「ドメイン名」の部分は IDN のルールが適用されるのですが, 「パス名」の部分は IRI のルールが適用されるわけで, それらが矛盾しているとかなり困りますが。
Re:重い (スコア:0)
grep-2.5 なんかでもこうやってます。
Re:重い (スコア:0)
追加されているようで、.inputrc に
set byte-oriented on
と書くと ja_JP とかのロケールでも byte 単位 で
処理されるみたいです。多少速いのかな?
Re:重い (スコア:1)
>と書くと ja_JP とかのロケールでも byte 単位 で
>処理されるみたいです。多少速いのかな?
速さは全然違います。このオプションをつけると実質Cロカールで動作したのと同等の処理になるようにしたはずです。(何か微妙な違いはあったかも、でももう忘れちゃいました)
特にコマンドラインに長い文字列を挿入する際のマルチバイト文字とワイド文字の相互変換の処理は膨大な回数繰り返されるので、長い文字列をcut & copyしてみるとbyte-orientedの場合との違いが見てとれるはずです。
Re:重い (スコア:0)
HANDLE_MULTIBYTE を undef してコンパイルしてみました。
メモリの消費量は 数10k 程度増えてるかな。
まぁ、重くはなりますけどね。
でも、いやなら、bash 使わなければいいのではないの?