iモードの絵文字をフォームから送信された時の処理をperlでしています。
具体的にはフォーム内容をデコードする前に、文章に絵文字が含まれているか16進数の状態でチェックします。含まれていれば、それらを10進数表記に変え、データとして保存しています。
ここまでは上手くいったのですが、問題が発生しました。
iモードからはShift_JISでデータが送信されてきますが、このデータの中に2バイト目の文字コードが絵文字の1バイト目の文字コードと同じであり、かつその次の文字の1バイト目が絵文字の2バイト目と同じだった場合に間違ってその文字を絵文字として処理してしまいます。
つまりある2文字の2バイト目と1バイト目が偶然絵文字と同じ文字コードだった場合に絵文字として取り扱ってしまうのです。(例:滲滲)
これを防ぐ方法が解る方がいらっしゃればご回答下さいm(_ _)m

※perlメモの「ただしくパターンマッチさせる」をShift_JISに変えてやってみましたが、うまくいきませんでした。。。

このQ&Aに関連する最新のQ&A

A 回答 (1件)

単なるパターンマッチでは上手く行かないので私は以下のようなスクリプトを書きました。

参考にして下さい。

sub han2zen{

local($input_string) = @_;
$temp_string = '';#空の文字変数を用意
$temp_position = 0;
$sjis_flag = 0;

$zenkana_table = '。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜';
&jcode'convert(*zenkana_table,"sjis");

while($temp_position < length($input_string)){
$temp_figure = substr($input_string,$temp_position,1);

#sjisの上位バイト
if ($sjis_flag == 1){
$temp_string = $temp_string.$temp_figure;
$sjis_flag = 0;
}elsif (ord($temp_figure) >=129 && ord($temp_figure) <= 159 || ord($temp_figure) >=224 && ord($temp_figure) <= 239){
$sjis_flag = 1;
$temp_string = $temp_string.$temp_figure;
}elsif (ord($temp_figure) >=248 && ord($temp_figure) <= 249){
$temp_position++;
$sjis_code = ord($temp_figure)*256+ord(substr($input_string,$temp_position,1));
#$temp_string = $temp_string."&#$sjis_code;".chr(59);
$temp_string = $temp_string."&#$sjis_code\x3b";
}elsif (ord($temp_figure) >=161 && ord($temp_figure) <= 223){
$temp_string = $temp_string.substr($zenkana_table,(ord($temp_figure)-161)*2,2);
}else{
$temp_string = $temp_string.$temp_figure;
}
$temp_position++;
}
$temp_string;
}
    • good
    • 0
この回答へのお礼

返事が遅くなってしまってスイマセン!
とても参考になりました。ありがとうございました。

お礼日時:2001/11/22 15:26

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

QShift-jisのPerlから、UTF-8、EUC、Shift-jisの3つのエンコードテキストを生成

Shift-jisで作ったPerlにて、テキストをEUC、UTF-8、Shift-jisにエンコードし外部検索サイト等にテキストリンクを飛ばしたいのですが、うまくいきません。

過去ログにUTF-8から、EUC、UTF-8、Shift-jisへのエンコード方法をみつけ
http://oshiete1.goo.ne.jp/qa3745875.html
試行錯誤しましたが、Shift-jisからはうまくいきませんでした。

perl のバージョンは5.8.8です。
ご教示のほどよろしくお願いします。

Aベストアンサー

こんなコードでテストしてみました。sjis <-> jis,euc,utf8 すべてうまくいけましたよ。

#!/usr/bin/perl
use Jcode;
print "content-type: text/html; charset=Shift_JIS\n\n";

$sjis='Japan,東京都千代田区霞が関1-1-1 コッカイビル1F';

print '<font color=red>';
print Jcode::getcode($sjis).' -> </font>';
$jis=Jcode::convert(\$sjis,'jis');
print '<font color=red>';
print Jcode::getcode($jis).' => </font>';
print $jis." <br>\n";
print '<font color=red>';
print Jcode::getcode($sjis).' -> </font>';
$euc=Jcode::convert(\$sjis,'euc');
print '<font color=red>';
print Jcode::getcode($euc).' => </font>';
print $euc." <br>\n";
print '<font color=red>';
print Jcode::getcode($sjis).' -> </font>';
$utf8=Jcode::convert(\$sjis,'utf8');
print '<font color=red>';
print Jcode::getcode($utf8).' => </font>';
print $utf8." <br>\n";
print "<br>\n";
print '<font color=red>';
print Jcode::getcode($jis).' -> </font>';
$sjis=Jcode::convert(\$jis,'sjis');
print '<font color=red>';
print Jcode::getcode($sjis).' => </font>';
print $sjis." <br>\n";
print '<font color=red>';
print Jcode::getcode($euc).' -> </font>';
$sjis=Jcode::convert(\$euc,'sjis');
print '<font color=red>';
print Jcode::getcode($sjis).' => </font>';
print $sjis." <br>\n";
print '<font color=red>';
print Jcode::getcode($utf8).' -> </font>';
$sjis=Jcode::convert(\$utf8,'sjis');
print '<font color=red>';
print Jcode::getcode($sjis).' => </font>';
print $sjis." <br>\n";
__END__

こんなコードでテストしてみました。sjis <-> jis,euc,utf8 すべてうまくいけましたよ。

#!/usr/bin/perl
use Jcode;
print "content-type: text/html; charset=Shift_JIS\n\n";

$sjis='Japan,東京都千代田区霞が関1-1-1 コッカイビル1F';

print '<font color=red>';
print Jcode::getcode($sjis).' -> </font>';
$jis=Jcode::convert(\$sjis,'jis');
print '<font color=red>';
print Jcode::getcode($jis).' => </font>';
print $jis." <br>\n";
print '<font color=red>';
print Jcode::g...続きを読む

Q文字コードを指定する際sjisなのかshift_jisかshift-jisなのか

お世話になります。
perl5.8において文字コードを指定or変換する際
shift_jis
shift-jis
Shift_JIS
SJIS
EUC_JP
EUC-JP
utf-8
utf8
-と_の違いや大文字小文字の違いなど記述の違いを良く見かけるのですが、実際決まった指定方法などはあるのでしょうか。
逆に文字コードを指定する際、●●のように指定しても無効で●●のように指定しないと有効ではないですよ。。みたいな。

またperlに限らずPHPやHTML、XMLなどではどうなっているのでしょうか

どなたかご存知の方いましたら
・上記3つの文字コードについてと
・perlのバージョンの違い、言語の違いなど

文字コードの文字列の指定に関する全般についてご教授願えませんでしょか。

宜しくお願い致します。

Aベストアンサー

文字コードを指定するモジュールによって、指定する文字列が違う場合があります。

たとえば、JcodeでシフトJISコードを指定するときはは'sjis'ですが、
Encodeでは次のような正規表現になります。

/\bshift.*jis$/i
/\bsjis$/i

これは、shift-jisでもShift_jisでもsjisでもSJISでもマッチします。
極端な話、shift(・∀・)jisでもマッチします(多分)

他の文字コードでも同様に正規表現でエイリアスが設定されていますので、詳しくはEncodeモジュールのperldocを参考にしてください。

Q文字コードの変換(Shift-JISからUTF8)

文字コードがShift-JISのCSVファイルを読み込み、UTF-8のテキストファイルに出力するのに
プログラムの中で変更しようとしているのですが、うまくいきません。出力ファイルの文字コードを
確認するとShift-JISのままです。
どなたか教えていただけないでしょうか?
ActivePerl v5.16.0を使用し、Encodeモジュールのfrom_toを使用しています。

#!/usr/bin/perl

use strict;
use warnings;

use utf8;
use Encode;

my $input_file="input.csv";
my $output_file="output.txt";
open (IN, $input_file) or die "$!";
open (OUT, ">$output_file") or die "$!";

while (<IN>){
chomp ($_);
my @data=split(/,/,$_);

for(my $i=0;$i<@data;$i++){
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換
$data[$i]=~s/\s+//g;
print OUT $_;
}
print OUT "\n";
}
close (IN);
close (OUT);

文字コードがShift-JISのCSVファイルを読み込み、UTF-8のテキストファイルに出力するのに
プログラムの中で変更しようとしているのですが、うまくいきません。出力ファイルの文字コードを
確認するとShift-JISのままです。
どなたか教えていただけないでしょうか?
ActivePerl v5.16.0を使用し、Encodeモジュールのfrom_toを使用しています。

#!/usr/bin/perl

use strict;
use warnings;

use utf8;
use Encode;

my $input_file="input.csv";
my $output_file="output.txt";
open (IN, $input_file) or die "$!...続きを読む

Aベストアンサー

あの、私のや他の回答をよく読んで考えてください。


for(my $i=0;$i<@data;$i++){
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換
$data[$i]=~s/\s+//g;
print OUT $_;
}

この部分は **** $_には何の影響も与えません ****
よって、** 出力に関することだけに注目したら **

for(my $i=0;$i<@data;$i++){
print OUT $_;
}

これと等価です。どこで「Shift_JIS からUTF-8へ変換」してますか?
$_は「while (<IN>){」の<IN>で1行読み込まれ、「chomp ($_);」で末尾の改行コードが削除されただけで、移行なにも変化していません。コードは入力のまま=Shift_JISです。それをそのまま出力すればShift_JISになるのが正解です。
しかも、項目数分だけ繰り返し出力されます。
(重複行になる、と#1に書いたのはchompのことを失念していた私のミスです)

@dataを変更したのなら、出力するのは@dataでしょう。
join(",", @data)とすれば、項目をカンマ区切りの文字列にすることができます。


あと#2にあったfrom_toの使い方。マニュアルをよく読みましょう
http://perldoc.perl.org/Encode.html#[$length-=]-from_to($octets,-FROM_ENC,-TO_ENC-[,-CHECK])
・$octetsを直接変換する
・$octetsの長さを返す
とあります。つまり
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8')
だと,$data[$i]には元の内容は破棄されて、文字列の長さになってしまいます。



各項目毎に処理したい、という意図はわかりました。

ですが、文字コードの変換が項目毎に違うなんてことはまず無いでしょう。
それならば、$_で1行をコード変換→splitして項目毎の処理、としてもいいのでは?

ついでにPerlIOを使って
open (IN, "<:encoding(shift_jis)", $input_file) or die "$!";
open (OUT, ">:utf8", $output_file) or die "$!";
とでもやれば、プログラム中はコードをあまり意識せずに文字列処理ができます。

あの、私のや他の回答をよく読んで考えてください。


for(my $i=0;$i<@data;$i++){
$data[$i]=Encode::from_to($data[$i],'shiftjis','utf8'); #Shift-JISからUTF-8に変換
$data[$i]=~s/\s+//g;
print OUT $_;
}

この部分は **** $_には何の影響も与えません ****
よって、** 出力に関することだけに注目したら **

for(my $i=0;$i<@data;$i++){
print OUT $_;
}

これと等価です。どこで「Shift_JIS からUTF-8へ変換」してますか?
$_は「while (<IN>){」の<IN>で1行読み込まれ、「chomp ($_);」で末尾の改行コ...続きを読む

Q文字コードEUC→SHIFT-JISにすると動作しません

http://cgikon.com/search/detail.php3?menu=1&cgi_id=412

上記の簡単なスクリプトを使いたいと思っています。
文字コードがEUCとなっており、そのままの状態で設置すれば動作します。

EUCではなく、SHIFT-JISにして動作させたいのですが、中に書かれている「EUC - JP」を「SHIFT - JIS」に書き換えて、またファイルの文字コードも「SHIFT-JIS」として保存しました。
またCSVデータも「SHIFT-JIS」に変換して保存。

変換したファイルをアップしてみましたが、表示される表の数値の箇所が真っ白になってしまいます。
一番上の行と一番左の列は表示されます。
足し算される数値の部分だけが表示されません。

どのようにすれば、EUCからシフトJISに変換して、動作させる事ができるのでしょうか。


アドバイスをお願い致します。

Aベストアンサー

> なぜシフトJISにすると、全角スペースがあるとダメだったのか分かりませんが、とりあえず解決して良かったです。

ShiftJISの場合、全角空白は 0x81 0x40 という並びです。

>echo " "|hexdump
00000000: 22 81 40 22 0A ".@".

見事に '@' が隠れているのでこれが誤動作の引き金になりえます。

Qjisコードで16進数の『3c』から始まる文字

だけが文字化けしてしまいます。今までそういった現象はまったく起きていなかったのですが、突然発生するようになりました。
文字化けの内容。
『治』が『。』『爾』が『「』
といった感じで、jisコードの3c20の+3から3c60の+2までの文字が半角カタカナに化けてしまいます。
コード内容は以下です。
#!/usr/bin/perl
#use KCatch qw( execdata );__DATA__
use CGI qw(:standard);
use Encode;
#use strict;
#use warnings;

require './jcode.pl';
require './mimew.pl';

#############################################
#処理開始
$query = CGI->new;

if(param('handleName')){
$handleName = $query->param('handleName');
}

if(param('nameLast')){
$nameLast = $query->param('nameLast');
#&jcode::convert(*nameLast,'euc-jp');
}

if(param('nameFirst')){
$nameFirst = $query->param('nameFirst');
&jcode::convert(*nameFirst,'euc-jp');
}

################################
#送信メール成型
$Mail_A= <<"EOF";
$handleName
$nameLast $nameFirst
EOF

##########################################
#コード変換
$Subject_A = &mimeencode($Subject_A);
$Subject_B = &mimeencode($Subject_B);
&jcode::convert(\$Mail_A,'jis');
&jcode::convert(\$Mail_B,'jis');

#受付側用を送信
open (SENDMAIL,"| $Sendmail -t -i");

print SENDMAIL <<"EOF";
To: $ToMailadd
From: $mailAddress
Subject: $Subject_A
MIME-Version: 1.0
Content-Type: text/plain\; charset="ISO-2022-JP\"
Content-Transfer-Encoding: 7bit

$Mail_A
EOF

close SENDMAIL;

です。足りない部分等ありましたら教えてください。

だけが文字化けしてしまいます。今までそういった現象はまったく起きていなかったのですが、突然発生するようになりました。
文字化けの内容。
『治』が『。』『爾』が『「』
といった感じで、jisコードの3c20の+3から3c60の+2までの文字が半角カタカナに化けてしまいます。
コード内容は以下です。
#!/usr/bin/perl
#use KCatch qw( execdata );__DATA__
use CGI qw(:standard);
use Encode;
#use strict;
#use warnings;

require './jcode.pl';
require './mimew.pl';

#######################...続きを読む

Aベストアンサー

$handleNameがEUCに変換されていないのではないでしょうか? $Mail_Aの合成部分で文字コードが混在しそうです。


後、文字化けとは一切関係ないですが、利用されていない「use Encode」が気になりました。jcode.plを使わずにすむと思います。


おすすめ情報