何となく Blog by Jitta
Microsoft .NET 考

目次

Blog 利用状況
  • 投稿数 - 591
  • 記事 - 18
  • コメント - 2182
  • トラックバック - 183
ニュース
  • 検索エンジンで来られた方へ:
    お望みの情報は見つかりましたか? よろしければ、コメント欄にどのような情報を探していたのか、ご記入ください。
It's ME!
  • はなおか じった
  • 世界遺産の近くに住んでます。
  • Microsoft MVP for Visual Developer ASP/ASP.NET 10, 2004 - 9, 2009
サイト内検索
広告

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

その他

わんくま同盟

同郷

 

元ネタ:管理人さんへひとこと

さらに元:文字列の全角半角判定

過去のエントリ:全角?半角?

お勉強:特番 Windows Vista の新文字セットが引き起こすトラブル(ITpro)

お勉強その2:小形克宏の「文字の海、ビットの舟」―― 文字コードが私たちに問いかけるもの(INTERNET Watch)


何というか、文字処理って、難しいですよ。

ごく最近、あるウェブサービスで住所を入力しました。「日本のどこか12丁目34番地」と。すると、「住所に半角文字が入力されています。全角文字だけを使用してください」と、エラーになりました。

なぜ?どうして?何のために?

郵便番号を ASCII 7bit の範囲で入力しろ、というのなら、まだわかります。なぜ住所から、ASCII 7bit の範囲を排除しなければならないのか。「わんくまハイツA棟」という住所は使ってはいけないの?それをおかしいと思いませんか?

「丈」という文字を名前に持っていらっしゃる方は多いと思いますが、「丈」の字は、本当は「��」(Vista なら表示される?右上に点がついている)、点がついていたりしませんか?「全角半角チェック」は、たいてい Shift_JIS にコード変換をして、1バイト文字か2バイト文字かで判別しますが、この字は Shift_JIS に割り当てがありません。すると、"?" に置き換わってしまいます。サロゲートペアなので、2つ。はい、「名前に半角文字が含まれています。全角文字だけを入力してください」って、怒られることになります。

もちろん、正規表現もこれに対応していません。「名前に「丈」の字がつく人」を検索しても、点付きの「丈」はヒットしません。全文検索するとき、異字体やサロゲートペア文字で書かれていると、ヒットできません。

文字列の全角半角判定(C# と VB.NET の質問掲示板)より:

□投稿者/ hei (2回)-(2007/08/08(Wed) 23:57:11)

私は銀行などに納品しているテキストファイルを生成しています。
納品形態は顧客ごとに違っていますが、
すべてShiftJISでフィールドによって全角・半角を分けています。
この経験から上の発言をしましたが、
全角半角を意識するように指示されることは珍しいですか?

私は、DOS 時代に UNIX と DOS の間でデータをやりとりしていたので、エンディアン問題や文字コードの問題には、Windows だけで仕事をしている人より慎重に向き合っていると思います。その上で、「なぜ Shift_JIS ?」と問いたい。全ての端末が Windows で、Shift_JIS のデータしか入力されないのであれば、それもひとつ。

ただし、この、狭い視野(あえてこの表現)で、「EUC_JP を使う UNIX は?メールは JIS-2022-JP だよ?EBCDIC なシステムを相手にするときはどうするの?」という件について、知らないで済ませるのは、どうかと思うのです。

私は独学で学んだためか、個人的な全角半角の定義は基本的に
「キーボードの全角・半角入力で入力されたもの」
程度の認識です。
みなさんがおっしゃっている「定義」の意味がいまひとつわからないのですが、
これ以降のレスで理解できたらと思います。

と、書きながら、その後には、

頻繁に出てくる文字で例を挙げます。
全角とは「0123456789」で、
半角とは「0123456789」です(あえて断言します)。

というのは、話が合わないのはどっちでしょう?

少なくとも、その直前に、

全角半角は、こういう表示上占める範囲を表す場合と、一文字が何バイトでできているかを表す場合があります。前者はプロポーショナルフォントの出現で意味を失い、後者はUTF-16では一定、UTF-8では3倍角や4倍角もありえる。

と、なぜ定義をしなければならないのか、出しています。今、あなたがご覧になっているこのページは、UTF-8 のコードが使われています。このコードでは、日本語の文字の多くは、3バイトです。"®" のような、Latain-1 で定義されている文字は、2バイトあります。欧文コードでは 0xae に定義されていて、1バイトなんですけどね。また、Vista ではメイリオ フォント、XP では MS UI ゴシック フォント、Mac では Osaka フォントで表示されていると思います。これらは、プロポーショナル フォントです。"l"(エル)と"m"(エム)で、表示に必要な幅が違います。ゆえに、何を持って「全角文字」「半角文字」というのでしょう?判別のための文字コードと、表示されるフォント、このふたつが一定の基準を満たさないと、「全角」や「半角」は問題にならないのです。

「私は Windows でしか仕事をしていないから、Shift_JIS が全てだ!」というのもいいでしょう。でも、本当に?Windows の内部コードは、とっくの昔に Unicode ですよ?開発環境も、少なくとも Visual Studio 6.0 の頃には、Unicode に対応しています。デフォルトは、Multi Byte Charactorset ですけど(ここ、文字集合と文字符号が一緒くたに扱われているという、突っ込み所)。API も、'A' と 'W' が用意されています。つまり、Unicode を扱うための準備は整っていて、そのための移行期間も十分に設けられています。大昔に書かれた、デバイス ドライバ寄りなプログラムのメンテナンスをしている私は、ほとんどの所を MBC で扱いながら、API 呼び出し直前に Unicode に変換しているコードに苛立っています。だれだ、こんな中途半端なコード書いたの!!

ユーザーが入力した「123-4567」と「123-4567」は違う郵便番号ですか?とあります。同じ郵便番号です。同じ郵便番号なのに、なぜ、これらの文字を対比するときに使う用語は、一般に「全角の数字・半角の数字」ではないですか?と分けてみたり、一般に「全角半角」という異なった文字を出力するのでこれらのチェック・変換は頻繁に行っています。のようなチェックが必要になったりするのでしょう?誰のための、何のためのチェックなの?同じなのだから、チェックする必要はないでしょう(郵便番号のフォーマットに一致しているかどうかのチェックは必要)。郵便番号の枠一杯に書いたときと、半分だけ使って書いたときで、別の文字になるのでしょうか?

しかし、実のところ、全角半角の区別をしなくていいのは、エンド ユーザだけです。プログラム製造に関わる人は、意識しなければなりません。なぜか。コンピュータが区別するからです。

人間は、文字を形で認識しています。このとき、「1」も「1」も、同じ字として認識します。しかし、コンピュータはそうではありません。コンピュータが認識するのは、それぞれの文字に割り当てられたコードです。コードが違うものは、別の字なのです。そのため、「1」と「1」は、別の字として認識されます。

.NET Framework の Regex クラスは、オプションによって同じに扱ってくれますが、それは .NET Framework の中だけの話です。そんな例外、この際無視します。

区別しないエンド ユーザが、区別するコンピュータに、直接データを渡してやることはできません。そこで、プログラムに携わる人は、区別をする/しないを切り替える緩衝材にならなくてはなりません。そのため、コンピュータが何を区別するのか、知る必要があります。

それなのに、考えなしに、「一般に、漢字モードで入力したものが全角、漢字モード OFF で入力したものが半角といわれている」から、そのまま受け入れてしまっていいのでしょうか?

私はこれまで学んできた中で、
全角半角のチェック・変換の質問には「VBのStrConv関数だよ」という
解説・回答はたくさん見てきましたが、
ここまで「厳密な定義」にこだわった意見にあったのは初めてです。
もちろんそれなりの意味があるのでしょうが、
結局理解できませんでした。

「今までは」、それでも良かったのですよ。Microsoft Charactorset CodePage 932 は、JIS だけでなく、NEC 拡張や IBM 拡張まで含んで定義されていたので、変換できない文字がなかったから。ところが、Oracle が Unicode を扱いだして、事情が変わりました。いわゆる、「Wave-Dash 問題」です。Oracle に "~" を登録して取り出すと、波の向きが反対になります。これは、Oracle 側が、CodePage 932 に合わせた文字セットを用意したことで、一応解決できています。9i 以降は、SJIS_TILDA だったかな?そんなコードに設定すれば、回避できるようになりました。

Unicode には、フォントを提供する人(になるのかな?)が自由に定義して良い領域があります。PC-9801 の頃の、「外字」に相当します。ここを使うと、当然文字化けが発生します。他の文字コードに変換できません。それを問題だと思わないのでしょうか。

こういった、これから発生してくるであろう問題が見えてくると、正規表現なんて使えて当たり前、そしてその限界に見捨てていて当たり前だと思っていますというのも、「当たり前」というのは言い過ぎとしても、納得できる意見のようだと思います。いかがでしょうか。

最初に出しているリンク先に、「日本の漢字には正字を元に、異字体、印刷標準字体がある」と書かれています。現在の所、これらには別々のコードが割り当てられ、同じものであるとは認識されません。今後、電子計算機による情報のデジタル化が進めば、同じ字であると認識されないことが問題になってくるでしょう(検索したときに検索できない、など)。そうすると、どれかの一文字に集約(「包摂」っていうんだって)される可能性もあります。このことを、日本の文化の衰退というのは、言い過ぎでしょうか?

投稿日時 : 2008年1月31日 22:36
コメント
  • # re: 再燃したので、もう一度
    アクア
    Posted @ 2008/02/01 0:02
    私も日本語の処理については調べましたがここまでの確認はしていませんでした。
    たいへん勉強になりました。ありがとうございます。


    > 大昔に書かれた、デバイス ドライバ寄りなプログラムのメンテナンスをしている私は、
    > ほとんどの所を MBC で扱いながら、API 呼び出し直前に
    > Unicode に変換しているコードに苛立っています。

    私の技術はJittaさんに到底及ばないですが、それでもこの一文でJittaさんがかなりのご苦労をなさったのであろう事は容易に想像できました。^^;
    私が言うのも変ですがお疲れ様です。^^;;;

    # 自分のBlogでも書きましたが、この様な経験を持たれた方の言葉は何よりも重みを感じます。
  • # re: 再燃したので、もう一度
    hei
    Posted @ 2008/02/01 1:33
    お世話になっています。
    大変勉強になる資料ありがとうございます。

    私は全角半角を再燃させたつもりはないのですが、
    前半部の私の引用部分に少し触れると、
    郵便番号の例は何か矛盾がありましたでしょうか?
    このことは、Jittaさんがすぐ下に書いている

    >しかし、実のところ、全角半角の区別をしなくていいのは、エンド ユーザだけです。
    >プログラム製造に関わる人は、意識しなければなりません。
    >なぜか。コンピュータが区別するからです。

    ということを言いたかったのですが。


    後半部の、

    >こういった、これから発生してくるであろう問題が見えてくると、
    >「正規表現なんて使えて当たり前、そしてその限界に見捨てていて当たり前だと思っています」というのも、
    >「当たり前」というのは言い過ぎとしても、納得できる意見のようだと思います。

    はよくわかりません。

    「これから発生してくるであろう問題」とは
    「渡辺・渡邊・渡邉」を同一視できない、ということでしょうか?
    これなら私も悩んだことのある問題ですが、
    正規表現とは全く関係ないように思うのですが・・・
  • # re: 再燃したので、もう一度
    ま@貧乏暇なし中(WANKUMA-ID:carron)
    Posted @ 2008/02/01 2:46
    Made in Japanize でGlobal Standard なコード体系ってあるんですか?
    UNICODEって日本語エリアのためにいくらか知らんけど相当な額のお金が裏で動いているのでしょう?
    FIFAランキングみたいにお金で買えないものはないのだから。日本が24位なんて納得出来ない。しかも韓国より上だし。
    正規表現なんていう誰が翻訳したんだか、言いえて妙な意味不明な日本語訳の暗号みたいな文法の文字並びに、日本文化の衰退を憂うのはいいでしょうけど、「正規表現なんて」てのは変でしょう?どー考えても。常に流れに流される日本人的な発想ではありますがw要するに僻みですね。
    正規表現いいじゃないっすか、使いましょうよ、将来を悲観しつつも、ね。だって、元の発想は、外人が手抜きしたいからでしょう?あれはどー見ても。拡張されてだいぶ単語っぽいのが多くはなってきたけどそれでもまだ暗号ですよね。

    中さんの書いていた「所詮~限界どーのこーの見限った」ってのは、あの人がただの日本人だからでしょ、なんでコンピュータ言語は英語っぽい文字で書かないとダメなの?なんでLOGOはGlobalStandardにならないの?MS社がLOGO出していたら中さんの不満は多少なりとも解消?までは行かなくてもあーゆー心の叫びみたいなある意味日本人として不甲斐ないというか、正規表現に代わるものを誰でもいいから提供してくれ、というか、要するに他人を当てにしつついいとこだけ持っていこう、流行の先端を走っちゃおうみたいな文言は記述されなかったと思います。コンピュータ言語という存在自体に不満があるのですね。本人は否定も肯定もしない、というか、へ?何ソレ?でしょけど。

    僕には被害妄想の僻みまるだしな文面に見えました。
    俺には無理だけど、誰か頼むよ、みたいな、ね。


  • # re: 再燃したので、もう一度
    よもやま
    Posted @ 2008/02/01 9:27
    「12345678901234567890」
    の文字列に対して、正規表現”[0-9]|[0-9]"で
    選択されてくる文字は、なんだろうか・・
    エディタによって動作が異なる場合も・・

    正規表現”[0-9]"でマッチするのは
    前半部分の「1234567890」だけ・・
    数字というひとくくりで検索したくても
    漢字コード体系にも目を配らざるを得なくなる。

    本当文字処理って難しいです。

  • # re: 再燃したので、もう一度
    よもやま
    Posted @ 2008/02/01 9:34
    "漢字コード体系"
    表現が適切ではありませんね。

    Ⅰで始まるローマ数字
    ①で始まる丸数字
    壱で始まる漢数字
    後記述漏れがあるかもしれませんが
    数字として[0-9]では拾い上げてくれない事を言いたかったわけです。

  • # re: 再燃したので、もう一度
    Orator
    Posted @ 2008/02/01 10:01
    # VB屋として、本題以外のところに反応。

    > 「VBのStrConv関数だよ」という
    旧VB の StrConv でも、一部、注意が必要な文字があるのでご注意を。
    Wide/Narrowの相互変換ができず、片方向変換のみの文字がありますので。

    以下、文字化けを避けるため、ChrW のコードで表記します。

    &H0022 → vbWide → &HFF02
    &H0027 → vbWide → &HFF07
    &H005C → vbWide → &H005C
    &HFFE5 →vbNarrow→ &H005C(NT系)または&HFFE5(9X系)
    &HFF3C →vbNarrow→ &HFF3C
    &H2018 →vbNarrow→ &H0027
    &H2019 →vbNarrow→ &H0027
    &HFF07 →vbNarrow→ &H0027(NT系)または&HFF07(9X系)
    &H201C →vbNarrow→ &H0022
    &H201D →vbNarrow→ &H0022
    &HFF02 →vbNarrow→ &H0022(NT系)または&HFF02(9X系)

    なお、上記を VB.NET + NT系の組合せで試したところ、VB6 + NT 系と同じ結果を返しました。
    (VB.NET + Win98 では試していませんが)
  • # re: 再燃したので、もう一度
    Jitta
    Posted @ 2008/02/02 11:11
    heiさん、コメントありがとうございます。

    > 郵便番号の例は何か矛盾がありましたでしょうか?
    snip
    > ということを言いたかったのですが。

    え???そうなんですか?え~~っ!!
    済みません、全然わかりませんでした。

     ん。。。だとすると、私はheiさんが、コンピュータとエンド ユーザとの緩衝材になれるだけの十分な知識をお持ちだとは思えないです。
     VB では StrConv かもしれません。では、他の言語では?なぜ、VB では StrConv をしなければならないのでしょう?Oratorさんが指摘されているとおり、StrConv では十分ではない場合もあるそうです。

    今までは、“たまたま”うまくいっていた。うまくいくデータしかなかった。
    それだけのことです。


    > 「渡辺・渡邊・渡邉」を同一視できない、ということでしょうか?
     そういうことです。な・・・Shift_JIS の範囲ですでにあるのかorz
    (言い訳:文字処理なんて扱ってないもん)

    > これなら私も悩んだことのある問題ですが
     ええ、なやんで、どうしました?どのように思いましたか?

     わんくま掲示板の方で、「反語である」と書きました。「それじゃいけない」ということを強調するための、「見捨てて当たり前」です。
  • # re: 再燃したので、もう一度
    hei
    Posted @ 2008/02/02 19:57
    >え???そうなんですか?え~~っ!!
    >済みません、全然わかりませんでした。

    次の部分に書いたつもりなのですが、この件に限らず、
    私は文章での説明が下手みたいです。

    >>現場のプログラマがするべきことは、
    >>「123-4567」と「123-4567」を同じ郵便番号とみなすことだと思うのです。
    >>おそらく質問者もこのような必要性があって質問したのだと思います。


    >私はheiさんが、コンピュータとエンド ユーザとの緩衝材になれるだけの十分な知識をお持ちだとは思えないです。

    その通りです。


    >VB では StrConv かもしれません。では、他の言語では?なぜ、VB では StrConv をしなければならないのでしょう?

    私に言っているのでしょうか?
    私が「VBのStrConv関数だよ」と書いた前後には、
    『これまで学んできた中で、~という解説・回答はたくさん見てきましたが』
    と書いていますが。

    ただ、私が多くの場所でStrConvを使っていることは事実で、
    Oratorさんが指摘された「誤変換」は知りませんでした。
    これはマズイですねぇ。


    >(言い訳:文字処理なんて扱ってないもん)
    そうだろうとは感じていました。
    失礼を承知で言わせてもらいますが、
    正規表現を知らないのではないかと思えてなりません。
    もちろん知っている必要はありませんが、
    http://bbs.wankuma.com/index.cgi?mode=red&namber=13465
    のような発言は正直どうかと思います。


    >なやんで、どうしました?
    どうにもなりませんでした。

    >どのように思いましたか?
    これをうまくマッチングさせることがシステム屋の力量でしょうね。

    >「それじゃいけない」ということを強調するための、「見捨てて当たり前」です。
    やはりよく分かりませんでした。
  • # re: 再燃したので、もう一度
    hei
    Posted @ 2008/02/02 20:03
    訂正

    ×私は文章での説明が下手みたいです。

    ○私は他者への説明が下手みたいです。
  • # re: 再燃したので、もう一度
    hei
    Posted @ 2008/02/03 18:55
    >>> これなら私も悩んだことのある問題ですが
    >>  ええ、なやんで、どうしました?どのように思いましたか?
    > どうにもなりませんでした。

    この問題の解決を試みているところは既に存在するそうです。
    完璧な方法ではなく、かなりの力技(としか言えません)でかなりの手間とコストがかかるため
    私のプロジェクトでは採用できませんでしたが。
  • # 正字・異字体・印刷標準字体
    安岡孝一
    Posted @ 2008/02/04 0:20
    「日本の漢字には正字を元に、異字体、印刷標準字体がある」と引用されてるのですが、これ、引用元はどこなんでしょう? 少なくとも私は、日経ITProにそんなこと書いた覚えはないし、小形さんがそんなこと書くとは思えないのですが?
  • # re: 再燃したので、もう一度
    Jitta
    Posted @ 2008/02/04 12:03
    安岡孝一さん、コメントありがとうございます。

    > これ、引用元はどこなんでしょう?

    ごめんなさい。これは言葉が足りなすぎました。「と書かれていると“理解しています”」です。
    と言うことは、私の理解が間違っていることがわかったのですが、いつかどこかで取り上げていただけるとうれしいです。
    そう理解した元は?とご質問がありそうですが、ごめんなさい、まだ探しきれていません。少しお時間ください。


    取り急ぎ、お詫びと訂正まで。
  • # CP932とJIS X 0212
    安岡孝一
    Posted @ 2008/02/04 16:58
    じゃ、とりあえず「日本の文化の衰退」は後回しってことにして、別の点を。
    「CodePage 932 は、JIS だけでなく、NEC 拡張や IBM 拡張まで含んで定義されていたので、変換できない文字がなかったから」ってのは、正直ウソなんじゃないかと思うんですけど。だって、JIS X 0212の文字(たとえば「?」)って、CP932に入ってないので変換できないでしょ? でも、Microsoftは、Windows 98で既にJIS X 0212をサポートしてたから、「今までは」じゃなくて、そもそも10年前から問題だったはずなんですけど?
  • # Re: CP932とJIS X 0212
    安岡孝一
    Posted @ 2008/02/04 17:04
    と書いたら、案の定、JIS X 0212の文字(76区31点の「鷗」)がクエスチョンマークに化けましたね。このサイトも表面的にはUTF-8だけど、中ではちゃんと処理できてないんだろうなぁ…。
  • # re: 再燃したので、もう一度
    Orator
    Posted @ 2008/02/04 19:15
    > StrConv では十分ではない場合もあるそうです。
    逆説的に、あの実装で十分に役に立つ場合もあるでしょうね。

    > Oratorさんが指摘された「誤変換」は知りませんでした。
    あの実装については、私は別に誤変換だとは思っていませんでしたが、
    hei さんは、具体的にはどの文字が「誤変換」だと思いますか?

    「片方向変換のみの文字」というのは、たとえば
     全角ひらがな→vbNarrow→半角カナ→vbWide→…
    がありますよね。

    平仮名については、比較的気が付きやすいのですが、あれらの文字は
    気が付かない人も多いので、注意した方が良いですよ、というのが
    先の発言の意図です。(実装の正誤を示したつもりはありません)
  • # re: 再燃したので、もう一度
    Jitta
    Posted @ 2008/02/04 19:38
    heiさん
    ごめんなさい。やっと、何に怒っているのか、理解できました。


    安岡孝一さん
    厳しいですね。
    元ネタで、heiさんがなにご立腹なのか、わかりませんでした。とりあえず、文字コードを意識してプログラムを作ったことがないのだろうと 思いました。このエントリは、文字コードを定義しようというものではなく、文字コードにも意識を向けてよ!を、主題にしています。私が不勉強なところも多々ありますが、(1)コードの違いによって問題が生じるということ、(2)現在のOSだけでなく各種ライブラリの実装では、日本語の扱いに注意が必要であること、(3)声を上げれば開発者が聞いてくれるかもしれないこと、を伝えるには、十分かと思っています。


    その意味で、heiさんが指摘されている投稿では、失礼がありました。heiさんにとっての十分、安岡孝一さんにとっての十分、私にとっての十分はそれぞれ違い、そこにまで口出しする必要はありませんでした。この点、heiさんにお詫びします。
  • # re: 再燃したので、もう一度
    Jitta
    Posted @ 2008/02/04 19:54
    アクアさん、コメントありがとうございます。

    私は浅いので、すぐグダグダですよ(苦笑)↑良い例



    よもやまさん、コメントありがとうございます。

    難しいです。たぶん、人間が曖昧さを許容する範囲と、機械が求める厳格さに大きな隔たりがあるのではないかと。この差が、機械は難しい、になっているのかな?


    Oratorさん、コメントありがとうございます。
    Orator先生にコメントいただけるとは、ドキドキです!色々お世話になっています。
  • # re: 再燃したので、もう一度
    hei
    Posted @ 2008/02/05 22:33
    >>Oratorさん

    >(実装の正誤を示したつもりはありません)

    自分でもちょっと引っかかってはいたので括弧付きで書きましたが、
    おかしい表現でした。すみません。
    私の意図した変換とはちがう、という意味です。

    >あれらの文字は 気が付かない人も多いので、注意した方が良いですよ

    とても参考になりました。
    ありがとうございました。
  • # re: 再燃したので、もう一度
    Jitta
    Posted @ 2008/02/05 23:00
    安岡孝一さん
    > 「CodePage 932 は、JIS だけでなく、NEC 拡張や IBM 拡張まで含んで定義されていたので、変換できない文字がなかったから」ってのは、正直ウソなんじゃないかと思うんですけど。

    http://itpro.nikkeibp.co.jp/article/COLUMN/20061122/254626/?ST=vista
    この図を、よく見直したら、思いっきり勘違いしていました。「NEC特殊文字」「IBM特殊文字」については、囲みがよくわからないし、はみ出しているようです。はみ出しているのはJIS-X-xxxなのかな?ん?Unicode2.1 とは、この図全体を指しているのか?それとも、NEC特殊文字はUnicode2.1からもはみ出しているのかな?
タイトル  
名前  
Url
コメント