Perlで文字数の計算

[上に] [前に] [次に]
Weasel 2000/03/03(金) 12:58:43
昨日はお世話になりました。

../200003/00030036.htm

さて、新たな質問があります。


メール送信フォームの改造版を作っていまして、

一つの項目にコメントがあります。

コメントの文字数を制限したくて、このラウンジを

検索したら、

../199809/98090087.htm

に、

全角の文字数:$n = $comment =~ tr/\xa1-\xfe/\xa1-\xfe/;

       $n = $n / 2;

半角の文字数:$m = $comment =~ tr/\x00-\x7f/\x00-\x7f/;

合計:    $count = $n + $m;

と考えられそうな説明がありました。

これって動くのでしょうか?

また、ほかによい方法があれば教えてください。


# 正規表現を使っていること以外、よくわからないので、

# あまりコピーペーストでスクリプトを作りたくないのです。(^ ^;

S-pore [HomePage] 2000/03/03(金) 18:43:54
漢字コードはEUCですよね?

> 全角の文字数:$n = $comment =~ tr/\xa1-\xfe/\xa1-\xfe/;

EUCの1バイト目は, 8E, 90〜9F, A1〜FE じゃありませんでしたっけ?
私のこの記憶が確かなら,↑のでは数えこぼしがでてくるような・・・。
ていうか,単純に

$str =~ s/[\x80-\xFF][\x80-\xFF]/k/g;
$len = length($str);

とかいう大ざっぱな判定で十分なような気が。(^^;

# 私は普段EUC使わないので何か間違ってたら誰か教えてください。

> また、ほかによい方法があれば教えてください。

私だったら全角は2文字分と見なしますが。(を)

S-pore [HomePage] 2000/03/03(金) 20:10:46
> EUCの1バイト目は, 8E, 90〜9F, A1〜FE じゃありませんでしたっけ?
> 私のこの記憶が確かなら,↑のでは数えこぼしがでてくるような・・・。

すみません。これは思い違いのようです。この部分は無視してください。

Weasel 2000/03/04(土) 18:52:58
すいません。レスが遅くなりました。

> $str =~ s/[\x80-\xFF][\x80-\xFF]/k/g;
> $len = length($str);

でやってみたいと思います。

> 漢字コードはEUCですよね?
いや、JISでやろうと考えています。

オオカミ 2000/03/04(土) 19:13:31
>いや、JISでやろうと考えています。
perlのCGIの中ではJISは使えませんよ!!
EUCが一番安全
SJISはメタ文字のハンドリングが必要

Weasel 2000/03/05(日) 00:56:46
> perlのCGIの中ではJISは使えませんよ!!

えっ、初めて聞きました!
jcode.plでjisに変換する機能があったので、
てっきり大丈夫かと、、、
メール送信はJISで行いたいのです。

この場合ってフォームから取り込んで、ECUに
加工して、文字数をカウントしてからJISに
変換するって流れになるのでしょうか?

saka 2000/03/05(日) 01:02:08
Perlの中でもS-JISの処理は行なえます。
但し 単純にマッチ処理だけで扱う事は不可能に近いと言えます。
簡単に漢字を扱うならEUCにした方が良いです。
S-JISの文字数カウントは、
$line = $comment;
# LFは切り捨て(処理に問題でるから)
$line = s/\n//;
while($line ne "") {
    if ($line =~ /^[\x81-\x9F\xE0-\xEF]/)
        { $n++; } # 2byte文字数
    else
        { $m++; } # 1byte文字数
    # 先頭の文字を削除する
    $line =~ s/^[\x81-\x9F\xE0-\xEF]//;
    $line =~ s/^.//;
}
$count = $n + m;
こんな感じですかね。
$lineの先頭の1文字づつSJISの漢字コードか調べて
カウントしていきます。
カウント後先頭の1文字を削除して次を調べています。

saka 2000/03/05(日) 01:04:42
漢字コードはJISでしたか..
もっと面倒な処理しないといけないですね。
直ぐには作れない。

saka 2000/03/05(日) 01:39:34
JISだとこんな感じかな動作は未確認
$line = $comment;
while($line ne "") {
    if ($line =~ /(.)\x1B\$[\@B]/) {
        $m += length($1);
        $line =~ s/(.)\x1B\$[\@B]//;
        if ($line =~ /(.)\x1B\([BJ]/) {
            $n += length($1) / 2;
            $line =~ s/(.)\x1B\([BJ]//;
        }
        else { } #エラーした時の処理(未実装)
    }
    else {
        $m += length($line);
        last;
    }
}
$count = $n + m;

>この場合ってフォームから取り込んで、ECUに
>加工して、文字数をカウントしてからJISに
>変換するって流れになるのでしょうか?
それがいいです。
送信直前までEUCで処理して送信直前でJISコードに変換した方が簡単です。

Ichi 2000/03/05(日) 07:14:15
そもそも文字数を制限する目的とはなんなのでしょうか。
巨大なメールの送信を拒否するためなら、文字数でなく
単にバイト数を数えればいいと思いますが。

B-Cus 2000/03/05(日) 08:05:57
> perlのCGIの中ではJISは使えませんよ!!
> EUCが一番安全
> SJISはメタ文字のハンドリングが必要
  「JIS エンコーディングをスクリプト中に書く」

  「JIS エンコーディングをデータとして扱う」
の区別がわかってますか? この場合はどれを使ってもかまわんでしょう。

> 文字数でなく単にバイト数を数えればいいと思いますが。
賛成。

あと、このスレッドで出てきた文字数を数えるサンプル
コードは、文字コード的にもコーディングスタイル的にも
ちょっとひどいと思います。

正しい文字コードについては
  http://hp.vector.co.jp/authors/VA001240/article/charcode.html
perl で日本語を美しく扱う方法については
  http://www.din.or.jp/~ohzaki/perl.htm
が参考になるでしょう。

saka 2000/03/05(日) 23:27:18
>あと、このスレッドで出てきた文字数を数えるサンプル
>コードは、文字コード的にもコーディングスタイル的にも
>ちょっとひどいと思います。
済みません。ヘボなコードを書きまして。

実用上パイト数を数える方法で良いと思います。
Perl上でEUC以外の文字コードをどう処理したら考えていたので書き込みました。

Weasel 2000/03/06(月) 16:35:39
> 実用上パイト数を数える方法で良いと思います。

私も今回これでいこうと思います。ということは

$count = length($hoge);

でよろしいのでしょうか?

Ichi 2000/03/07(火) 05:12:59
それで大丈夫です。

[上に] [前に] [次に]