このページは福井県立大学の田中求之が2006年1月まで運用していた Mac のサーバ運用に関する会議室 「Web Scripter's Meeting」の記録です。情報が古くなっている可能性がありますのでご注意ください。

xReplaceでの、”法”と"@"との関係

発言者:山本 武
( Date Thursday, December 11, 1997 08:25:59 )


xReplaceについての質問です。

 先日、”法”という字の含まれるテキストファイルにおいて
xReplace afile search "@" replace tab
としたところ、文字化けが起きることを発見しました。

 実は MacPerl5でも同様の現象がおきているので何か共通の
問題では無いかと考えています。

 他にも同じように化ける可能性のある漢字等があるんじゃないかと
思って、ちょっと心配になっています。情報の提供をお願いします。

→  Hora's Homepage

田中求之 さんからのコメント
( Thursday, December 11, 1997 15:14:32 )

法という字の2バイト目が @ と同じコードのため、ScriptCode に関係なく置換を
行う(処理する文字列のコードに関係なく単純な処理を行う)ものでは、おっしゃる
ような文字化けが起こります。

xReplace を使うかぎりは、この問題は完全には回避できません。

処理を行う際に、文字列の ScriptCode (何語のどんなコードによる文字列か)を
指定できるものを使うと、この手の2バイト文字が置換によって文字化けするのを防ぐ
ことができますが、置換を行う osax でこの機能を持ったものはなかったと思います。

山本 武 さんからのコメント
( Thursday, December 11, 1997 22:36:53 )

 やっと理屈がわかったので安心しました。
やはり、1バイト文字1字のパターンマッチは
危険度が高いと言うことですね。
 Perlにパッチを当てる技量があればなぁとは
思うのですが。私の力ではなんともしがたいです。

大変、参考になりました

→  Hora's Homepage

前薗 健一 さんからのコメント
( Thursday, December 11, 1997 23:55:33 )

Shift JIS の 1 byte 目のコードの判定を行うかどうかという
問題ですので、やろうと思えばやれますね。

ま〜、面倒ですけれども。(^^;;

重松修 さんからのコメント
( Friday, December 12, 1997 09:06:37 )

この辺は、ToolBoxのMungerだと常についてまわる問題ですね。
# 私も以前同じ質問をしました。(^^;;

対象の文字列が短い場合は、Mungerでなくて、ReplaceTextを使えば、2バイトを
認識するのでデータが壊れる事もないと思うんですけど。

ただ、この場合も、“@”と“@”は区別されるし、私も自作のテキストエディタ
の検索ルーチンで、こういうスクリプトの問題、ケースやサブセットを判断/無視
などどうするか悩んでいます。

AppleScriptの場合は、検索対象語句を飯森さんのOSAXでサブセット変換すれば、
とりあえず、いわゆる半角全角、大文字小文字は統一がとれた形にできるんですが、
スクリプトを指定しての、検索置換は自分でOSAXなりを作る必要があるかもですね。
AppleScriptでループさせてたら、気が遠くなるくらいおそそうですから。

xReplaceに検索文字列を16バイトまでに制限したRelpaceTextを使うルーチンが
追加されれば、すくなくとも、“@”をTABに変換するってのは完全に問題なく
高速に実行できますね。これにより日本語以外の2バイト文字でも安心して使える
ようになると思うので、次回のバージョンアップの折にはぜひ検討して下さい。

田中求之 さんからのコメント
( Friday, December 12, 1997 14:13:27 )

>xReplaceに検索文字列を16バイトまでに制限したRelpaceTextを使うルーチンが
>追加されれば、

根本的な作り替えが必要になるのと、検索文字列が 16 バイトという制限がつくのが
嫌なので、今のところ対応は考えていません。 Quick & Dirty を信条としてます
ので (^_^;;

私の使っているコンパイラが、Script Manager 関連の Toolbox をうまくコンパ
イルしてくれない(コンパイルできるが、実行するとクラッシュするコードをはく)
という問題を抱えていることもあって、Script Manager の世界には入っていけない
ということもあるんですよ。


なお、AppleScript's text item delimiter の操作による置換の場合は、
2バイト文字を認識の上、置換ができるようですので、この方法をとるのが解決
策になると思います。

on replace(myStr, searchStr, replaceStr)
  set oldDel to AppleScript's text item delimiters
  set AppleScript's text item delimiters to searchStr
  set myStr to text items of myStr
  set AppleScript's text item delimiters to replaceStr
  set myStr to myStr as string
  set AppleScript's text item delimiters to oldDel
  return myStr
end replace

このハンドラーを使うと、

replace("法律に@関して法則を@学ぶ", "@", "--")

----> "法律に--関して法則を--学ぶ"

になります

前薗 健一 さんからのコメント
( Saturday, December 13, 1997 00:36:32 )

以前、田中さんからのコメントがあったと記憶しているのですが。

xReplace osax は言語に問わずに置換を行うという仕様だったと思います。

何を言いたいかといいますと、日本語とヨーロッパの言語は
全然違いますが、コンピュータでデータを扱う時に、7 bit とか
8 bit の問題があるのです。

このあたりをうまく吸収するには、結構、問題があるんですよね。

xReplace osax を使うのが日本人だけだったら日本人に都合のよい、
仕様にすればいいのですけど、xReplace osax は世界中で利用されて
いるんですよ。

重松修 さんからのコメント
( Saturday, December 13, 1997 16:54:48 )

>Replace osax は言語に問わずに置換を行うという仕様だったと思います。

はい。承知しています。

日本仕様にしてほしいというのではなく、スクリプトが指定できるようになれば
いいな、という程度の気持ちです。不便で不便で凄く困っていると言うものでは
ありませんので。

要するに、
  ReplaceText "法@" searh "@" replace "-" script smJapanese
的なものです。

田中先生のご説明で、SciriptManager対応が難しい事や、AppleScript's text
item delimiterの工夫でスクリプトを識別しながらの置換が可能である事が
わかりましたので、私の希望はすて置いていただいて結構です。

お騒がせいたしました。

前薗 健一 さんからのコメント
( Sunday, December 14, 1997 00:08:22 )

to 重松修 さん

田中さんには面倒なことでしょうけど

xReplace afile search "@" replace tab as SJIS とか
xReplace afile search "@" replace tab by SJIS

みたいな文法があればいいんでしょうね。

重松修 さんからのコメント
( Sunday, December 14, 1997 23:14:29 )

プログラム一般、という事で、xReplaceについてではないのですが、現在
田中先生のOSAXを利用させていただいていたCGIをFutureBASICに移植する
作業をしているのですが、ちょっと困っています。

'post'で受け取ったPost ArgumentsをURLデコードして、各項目に分解する
時なのですが、後で分解しやすいように、URLデコード時に“&”を<NUL>($00)に
に置き換えています。

田中先生のOSAXを使わせていただいた場合はこの辺はすでにリストで渡してくれる
のですが、FutureBASICにはリストがないので、itemsToListのような感じで、
ハンドルをデリミタを指定して、指定した項目を抜き出して、新しいハンドルを
作って戻してくれるようにしたいと思っています。
# AppleScirptのリストは内部的にはどういう表現(形式)なのでしょうか?

例えば、ハンドル(hndl&)の中身が“トヨタ,ホンダ,日産,マツダ”だったとして、

delimiter% = ASC(",")
newHndl& = FN getItem(hndl&,4,delimiter%)

とすると、newHndl&に“マツダ”を入れて返すようにしたいのです。

現在は、MUNGERでデリミタを検索してそれによりオフセットを求めて切り抜きを行って
いるのですが、これだと先の“@”同様、誤った位置で切ってしまいそうな気が
します。

ReplaceTextはその名の通り、どうやら置換しか能がないようなので、他のルーチン
をあたらなければと思うのですが、MUNGERの高機能版というか、例えば、

YAMADAとYamadaやyamadaを同一視(大文字,小文字を無視)したり、あるいは、
YAMADAとYAMADAやヤマダ(半角含む)を同一視したりして、スクリプト検索
を識別して検索する事はできるのでしょうか?

検索対象をトランスリタレーションで変換してから検索すれば、あたりがあるかないか
は分かるんですが、オフセットが意味を持たなくなるし、会議室のメッセージの
検索機能を作ろうと思うのですが、悩んでいます。

それから、MacOS 8にはText Encode Converterってのがあるみたいですが、
これで、SJISとJISやEUC,UNICODEのコード変換が可能なのでしょうか?
# 流し読みした範囲では可能なように見えたのですが。

漢字コードに関しては、前薗さんに教えていただいた、日本語情報処理を
参考にしてFBでもう素手に書いてあるので、特に必要は感じてないのですが、
どうせなら、中国語とか、そういうのもちゃんと使えるようにしたいなとか
思っています。

前薗 健一 さんからのコメント
( Monday, December 15, 1997 02:45:14 )

BASIC でも配列を使えますよね。
確か、dim xxx とか宣言すればよかったと記憶しています。

BASIC は忘れてしまったので C の場合ですと

char list[4][8] = {"トヨタ","ホンダ","日産","マツダ"};

とか

char list[4][8];
list[0] = "トヨタ";  // または
strcpy(list[0], "トヨタ");

みたいな感じでリストの設定をします。
で2番目のリスト項目(ホンダ)が必要な時は

char* item = list[1];

のような感じで取り出します。

> YAMADAとYamadaやyamadaを同一視(大文字,小文字を無視)

これは検索する文字列と、検索される側の文字列のアルファベットの
大文字、小文字を統一してから検索するという作業が必要です。

> YAMADAとYAMADAやヤマダ(半角含む)を同一視

アルファベットと日本語が混在する場合はそれなりの辞書を自前で
作る必要があります。

BASIC でも出来ると思います。

重松修 さんからのコメント
( Monday, December 15, 1997 13:02:40 )

前薗さん、アドバイスありがとうございます。

BASICにも配列はあります。ただし、通常の配列は固定長で中身が文字列としても、
それらも固定長になります。しかも、パスカル文字列しか扱えないので、最大
255文字までしか扱えません。INDEX$というちょうどSTR#リソースのように可変
長(項目数や各項目の長さ)でデータを扱える配列(もどき)もあるのですが、
やっぱり、パスカル文字列です。

そこで、現実的な問題としては投稿されるメッセージがわずか255文字におさまることは
稀だし、'post'で渡されるデータがつながって渡される以上、やはり切り抜かざるを
えません。

現状は、とりあえずMUNGERを使っているのですが、デリミタに$3Fまでの文字を
使えば、2バイト文字の下位バイトとぶつからないそうなので、その範囲をデリ
ミタに使用することで問題を回避する事にしました。
# “@”って$40なんですね。。。ちょっとの差(^_^;;

検索・置換については、Jeditなどで大文字小文字や全角,半角を無視して検索
できるので意外に簡単なのか、と思ってたのですが、やはり面倒臭いのですね。

田中求之 さんからのコメント
( Monday, December 15, 1997 14:10:18 )

置換の話まで含めると話が長くなりますので(基本的には、前園さんの指摘のように
自前でスクリプトを組むしかないでしょう。Text code converter を利用すれば
漢字コードは、Unicode も含めて、相互の変換は可能です。たしか、先日、開発
者用のドキュメントもリリースされてました)、post の処理だけに話を限ります。

FutureBASIC については全く知らないのですが、post を処理する際に、
デコードと、データの項目ごとの切り分けも同時に行うのが確実です。
ですから、項目ごとのデータを別々のハンドルとして確保しておいて、
そのハンドルを配列に入れておけばよいのではないですか?

つまり、ハンドルの配列を作るということですね。これであれば、配列の
データのサイズの制限などは一切気にする必要はありませんよね?





前薗 健一 さんからのコメント
( Tuesday, December 16, 1997 00:20:30 )

補足しておきます。

> YAMADAとYAMADAやヤマダ(半角含む)を同一視

YAMADAとYAMADAであれば、辞書を使うことなく、1 byte の
アルファベットと2 bytes 文字のアルファベットを比較することは
プログラムで可能です。が、ここにヤマダが入ると辞書が必要
です。

山本 武 さんからのコメント
( Tuesday, December 16, 1997 23:20:48 )

 ●皆さんの会話を聞いているだけで本当に勉強になります。
 (理解しきれない部分も多くあるのも本当ですが、本当に有り難いです)

 特に、このスレッドの発端となった"@"の置き換え自体が
 AppleScript's text item delimiters

→  文字列置換の速度の比較