CGI-BBS > 基礎 > jcode/jcode.pl > 自作検索システムで"ー"を含む文字を検索できません


カレッヂ
カレッヂ


質問者 銀杏秋刀魚  投稿日 11/15(木) 10:24:10
検索システムで、"マーブル"などのように
全角で"ー"が含まれていると、検索ができません。

$data =~ s/%([a-fA-F\d]{2})/pack("C", hex($1))/eg;
このように文字変換すると、"ー"はどうなってしまうのでしょうか?
その後、
#半角カタカナ→全角カタカナ
&jcode'h2z_sjis(*data);
# Shift-JIS 変換
&jcode'convert(*data,'sjis');
こうしてできた、$dataを全角のデータベースから、検索しています。

どうしたらよいでしょうか?教えてください。


回答者 しあわせのツボ  [削除]  投稿日 11/15(木) 11:39:32
まず「検索できない」とはどういう状態ですか?
単にヒットしないのか、別の文字と見なされてしまうのか、サーバエラーが出るのか、など様々な状態が考えられ、それぞれ考えられる原因や対処法が違います。

とりあえず類似の事例:
http://www.rescue.ne.jp/CGI-BBS/database/database/20010329002830.shtml
質問者 銀杏秋刀魚  [削除]  投稿日 11/17(土) 14:49:59
説明不足で申し訳ありません。

検索されないとは、別の文字にヒットするのでも、サーバーエラーに
なるのでもなく、画面が真っ白になります。
該当なしの場合は、「該当なし」と表示する記述はしています。

教えていただいた
quotemeta($data);を入れてみましたが、結果は同じでした。
プログラムの概要を以下に書いて見ます。
************************************************************
ブラウザーから入力したものを、$dataとして、POSTで受け取ります。
その後、

#日本語処理
$data =~ s/\+//g;
$data =~ s/%([a-fA-F\d]{2})/pack("C", hex($1))/eg;
quotemeta($data);
この$dataから、必要な入力分を$seibunmeiとし、
#半角カタカナ→全角カタカナ
&jcode'h2z_sjis(*seibunmei);
# Shift-JIS 変換
&jcode'convert(*seibunmei,'sjis');
この$seibunmeiを用いて、全角で入っているデータ$data[1]を
検索します。
if ($data[1] =~ /$seibunmei/i){
}
************************************************************
実現したい事は、半角でも全角でも入力してきたキーワードを
全角のデータからヒットさせたいのです。
どうしたら、よいでしょうか?

回答者 まさ  [削除]  投稿日 11/17(土) 19:24:33
うまく検索させることはCGI(Perl)では結構難しいです。
じゃあ無理かと言えば可能です。

たとえば
if ($data[1] =~ /$seibunmei/i)
これは文字コードがsjisならメタ文字が含まれる可能性があるのでうまくいきません。

基本的に検索はsjisではやってはいけません。
自分で文字コード判定するルーチンを作れるのならsjisでやってもいいでしょうけど、
そうでなければやめておきましょう。例えば半角カタカナは文字コードがsjisなのか
eucなのか判断できません。ここでまずスクリプトが混乱を起こします。例えばJavaScript
などでCGIを呼び出す前に半角カタカナをはじけばいいのすが、

>実現したい事は、半角でも全角でも入力してきたキーワードを
>全角のデータからヒットさせたいのです。
>どうしたら、よいでしょうか?

こういう仕様があるのなら使えません。

では解決方法を、

まずフォームがあるページをeucにします。
<meta http-equiv="Content-Type" content="text/html;charset=EUC-JP">
これも必ず入れておいて下さい。

フォームデータの受け取り方は、

if ($ENV{'REQUEST_METHOD'} eq "POST") {    read(STDIN,$tmp,$ENV{'CONTENT_LENGTH'});
}
else { $tmp = $ENV{'QUERY_STRING'}; }

@pairs = split(/&/,$tmp);
foreach $pair (@pairs) {
    ($name, $value) = split(/=/, $pair);
    $value =~ tr/+/ /;
    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
    &jcode::convert(\$value, 'euc');
    $form{$name} = $value;
}

こう言う風にします。CGI.pmを使ってもいいです。

半角を全角にするには
$words = $form{'words'};
&jcode::h2z_euc(\$words);
こうすればいいでしょう。

問題の検索の部分は
if ($data[1] =~ /$seibunmei/i)
この部分ですね。
これは

検索対象文字を$targetとすれば、

$ascii = '[\x00-\x7F]';
$twoBytes = '[\x8E\xA1-\xFE][\xA1-\xFE]';
$threeBytes = '\x8F[\xA1-\xFE][\xA1-\xFE]';

if ($target =~ /^($ascii|$twoBytes|$threeBytes{2})*$words/i) { $found = 1;}
else { $found = 0; }

$foundが1でヒットしたという事です。

まだまだ不備があるのですが、概ねこんな感じです。
文字コードがeucでも
if ($target =~ /$words/i)
とはできません。何故上のようになるかは自分で考えて下さい。
質問者 銀杏秋刀魚  [削除]  投稿日 11/22(木) 17:04:30
どうもありがとうございました。
やっと意図したとおりに、動くようになりました。
ご指導ありがとうございました。

やはり、まだ完全に文字コードについて理解しておらず、
文字コードについて理解しないとすぐ壁にぶつかってしまいますね。
もう一度、勉強してみます。

このページは終了したので返信(回答)は書きこめません

Web裏技