- ベストアンサー
Perl 正規表現について
Perlに関していつもお世話になっております。 今回も正規表現に関する質問をしたいと思います。 「あ、あい、あいう、あいうえ、あいうえお」というハッシュが存在するときに、「{あ}は○○回出ました。」「{あい}は○○回出ました。」とそれぞれ表示させるコードを組もうと思います。 前回までで皆様に教えていただいたことを元に組んでみました。 #!/usr/bin/perl use warnings; use strict; use utf8; use Encode; my %word_of = ( 'あい' => 0, 'あいう' => 0, 'あいうえ' => 0, 'あいうえお' => 0, 'かき' => 0, 'かきく' => 0, 'かきくけ' => 0, 'かきくけこ' => 0, ); foreach my $search_key ( keys %word_of ) { foreach my $word ( keys %word_of ) { if ( $word =~ /$search_key/ ) { $word_of{$search_key}++; } } } foreach my $key ( sort ( keys %word_of ) ) { # utf8, shiftjis eucjp ... print encode( 'utf8', "「$key」 は $word_of{$key} 回出ました" ), "\n"; } これを出来ればeucjpで組みたいのですが、可能でしょうか? 私の思いあたる点、utf8表記の部分をeucjpに直しただけではエラーが出てしまいます。 よろしくお願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
(1)何故あまりお勧めできないのでしょうか? 少し遠回りして話しましょう。 http://xiaoxia.exblog.jp/2290810/ や http://kototubo.exblog.jp/2274040 などでも話題になったことがありますが、次のコードを見て下さい。 my $str = 'アは'; print $str, "\n"; my $del = '△'; print $del, "\n"; $str =~ s/$del//; print $str, "\n"; このコードは文字列 $str に含まれる △ を削除するというものです。 これを euc-jp で保存し実行すると次ようになります。 アは △ ハ 'アは' から '△' を削除すると 'ハ'が出てきました。 これは 'アは' が バイナリで見ると a5 a2 a4 cf であり、 '△' はバイナリで見ると、a2 a4です。 a5 a2 a4 cf から a2 a4 を削除すると、a5 cf になり、これは'ハ'になり ます。したがって、日本語などのマルチバイトをそのまま、コード内で使 うことは、とても危ういことです。 では、次にuse encodingを使ってみましょう。 use encoding 'euc-jp'; my $str = 'アは'; print $str, "\n"; my $del = '△'; print $del, "\n"; $str =~ s/$del//; print $str, "\n"; これを実行すると、 アは △ アは となり、期待した結果になります。 use encoding をすると何が起こるのでしょう。use encoding をすると、 実行時に Perl スクリプト内で使われるマルチバイト文字は、フラグ付き UTF-8 (flagged UTF-8) に変換され、標準入出力はフラグ付き UTF-8 に自 動でエンコード、デコードされます。したがって、ユーザからは euc-jp で コードを保存し、標準入力は euc-jp を受け取り、標準出力は euc-jp で出 力することになります。つまり、euc-jp でコードを書いて実行するだけで ユーザは特に何も考える必要がなくなるのです。 しかし、Perl にとっては、UTF-8 がもっとも自然で楽なエンコード方式な のです。したがって、Perl スクリプトは UTF-8 で書き、use utf8し、入 出力のときエンコード/デコードするのがお勧めです。 euc-jp の環境であれば、UTF-8 で書いて、以下のようにすれ標準入出力 を euc-jp を自動でエンコード/デコードされます。 use utf8; binmode STDOUT, ":encoding(eucjp)"; binmode STDIN, ":encoding(eucjp)"; euc-jpで書かれたファイルの場合は、 open my $fh, "<", $file or die "$file : $!"; binmode $fh, ":encoding(eucjp)"; あるいは open my $fh, "<:encoding(eucjp)", $file or die "$file : $!"; などどすれば、euc-jp で書かれたファイルは、Perl で読むときは、フラグ 付き UTF-8 に自動で変換されます。これ以外にも Encode モジュールを を使う方法もありますが、binmode で事足ることも多いでしょう。 (2)use strictは使用しないでも問題はありませんか? use strict はチェッカとして役割があるので、通常は付けたほうがよいで しょう。つぎのコードを見て下さい。 #!/usr/bin/perl my $val = 'Yamada'; print "Konyaga $va1 da\n"; これを実行すると、 Konyaga da と出力されます。 よく見るとわかりますが、$va1と$val は va'いち' と va'える'となってい ます。use strict を付けるとこういった間違いを指摘してくれます。 use strict を付けるとなぜ動かないのか、少し調べたほうがよいと思いま す。よくある間違いとしては、 ・変数を 使用前に my (または our) で宣言していない ・ファイルハンドラを my (または our)で宣言していない × open FH, "<", $file or die "$file : $!"; ○ open my $fh, "<", $file or die "$file : $!"; また、CGI::Carp を使えば、ブラウザ上にエラー内容が表示されます。 #!/usr/bin/perl -T use strict; use warnings; use CGI::Carp qw(fatalsToBrowser); my $val = 'Yamada'; print "Konyaga $va1 da\n"; これをブラウザで開くと Software error: Global symbol "$va1" requires explicit package name at foo.cgi line 7. となって、どこがおかしいかわかります。
その他の回答 (3)
- ryu_chan
- ベストアンサー率37% (69/186)
use encodingがお薦めできない理由は、これがスコープをもっていないことと、 Perl IOレイヤーを勝手に操作することです。 自分の書いたソースファイルだけに影響を及ぼすだけならいいのですが、他の ソースファイル(モジュール)を取り込んで利用するときに、そのソースファ イルにまで影響が及びます。 詳しくは以下サイトをご覧ください。 [Perl] encoding プラグマについて http://scape.blog.so-net.ne.jp/2008-09-06
お礼
回答ありがとうございます. URLとても参考になりました!
- _--_1l1_1_
- ベストアンサー率67% (102/152)
use encoding を使えばできます。実はあまりお勧めしません。 ロジックは自分の趣味に合わせて変えてありますが、意味はありません。 #!/usr/bin/perl use strict; use warnings; # use encoding はレガシーな Perl スクリプトを動かすときのみ使用すること # 通常は、utf-8 で保存し、use utf8 する # http://blog.livedoor.jp/dankogai/archives/51221731.html # ソースを euc-jp で記述し、標準出力を shift-jis にする例 # 標準入出力も euc-jp であれば、use encoding 'euc-jp'; だけでよい。 use encoding 'euc-jp', STDOUT => 'shift-jis'; my %word_of = map { $_ => 0 } qw( あい あいう あいうえ あいうえお かき かきく かきくけ かきくけこ ); foreach my $search_key ( keys %word_of ) { foreach my $word ( keys %word_of ) { $word_of{$search_key}++ if $word =~ /$search_key/; } } print "「$_」 は $word_of{$_} 回出ました\n" foreach ( sort ( keys %word_of ) );
補足
回答ありがとうございます。 早速実行してみようと思います! 2点ほどお尋ねします。 (1)何故あまりお勧めできないのでしょうか? (2)use strictは使用しないでも問題はありませんか? 組み込みの際にどうしてもエラーが出てしまうため、ひとつひとつ確認していたのですが、use strictを実行したときにプログラムが正常に動かなくなってしまいます。 行数が多くて見落としているのが原因かもしれませんが、それ以外でuse strictを実行したときに正常に動かなくなる原因はあるのでしょうか? 初歩的なミスでしたら申し訳ありません。 頂いたプログラミングについて不明な点がありましたら、また伺う形になりますが、そのときはよろしくお願いいたします。
- Tacosan
- ベストアンサー率23% (3656/15482)
・「eucjp で組みたい」とはどういうことでしょうか? 文字列を EUC で書きたい? 出力を EUC にしたい? その他? ・「utf8表記の部分をeucjpに直しただけではエラーが出る」というのは, 具体的にはどのようなプログラムにしたらどのようなエラーが出るのでしょうか?
補足
回答ありがとうございます。 >・「eucjp で組みたい」とはどういうことでしょうか? 文字列を EUC で書きたい? 出力を EUC にしたい? その他? 文字列をEUCで書きたいに該当します。 組み込もうとしているcgiの文字コード指定形式がEUCなのもあり、出来ればEUCで試みたいと思っております。 >・「utf8表記の部分をeucjpに直しただけではエラーが出る」というのは, 具体的にはどのようなプログラムにしたらどのようなエラーが出るのでしょうか? 上記に記載したコードについて、utf8表記の箇所を全てEUCに変換したところ、うまく動きませんでした。 その後utf8に文字コード指定をしたところ、コード自体が文字化けしてしまい、utf8での動作確認をすることが出来ませんでした。 また不明な点がございましたら、随時応答します。 Perlの扱いにまだ慣れてない部分がありまして、もしかしたら初歩的なミスをしているかもしれません。 申し訳ありませんが、よろしくお願いいたします。
お礼
回答ありがとうございます. ご丁寧に説明していただき,とても感謝しております! おかげですべての問題が解決し,プログラムも正常に動くようになりました. ありがとうございました.