perl print文で日本語表示するには

このQ&Aのポイント
  • perlのプログラムで、use utf8が宣言されていない時は、print文で日本語が正しく表示されるが、use utf8が宣言されている時は、print文で日本語が正しく表示されないかエラーになる。
  • encode('utf-8', $string)やencode('cp932', $string)を試してみたがうまくいかなかった。
  • 解決方法は不明。
回答を見る
  • ベストアンサー

perl print文で日本語表示するには

perlのプログラムで use utf8が宣言されていない時(test1.pl)は、 print文で日本語が正しく表示されるのですが、 use utf8が宣言されている時(test2.pl)は、 print文で日本語が正しく表示されないかエラーになります。 encode('utf-8', $string)やencode('cp932', $string) も試してみましたがうまくいきませんでした。 どのようにすればよいでしょうか。 ---test1.pl------------------------------------------------ #!C:/perl/bin/perl use strict; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year += 1900; $mon += 1; my $string="$year年$mon月$mday日 $hour時$min分$sec秒\n"; print $string; ----------------------------------------------------------- 実行結果 OK 2018年12月26日 9時36分6秒 ----------------------------------------------------------- ---test2.pl------------------------------------------------ #!C:/perl/bin/perl use strict; use utf8; use Encode; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year += 1900; $mon += 1; my $string="$year年$mon月$mday日 $hour時$min分$sec秒\n"; print $string; #print encode('utf-8', $string); #print encode('cp932', $string); --------------------------------------------------- 実行結果 NG (PC1 Windows7 ActivePerl) Wide character in print at D:\test\test2.pl line 11. Global symbol "$year年" requires explicit package name (did you forget to declare "my $year年"?) at D:\test\test2.pl line 8. Global symbol "$mon月" requires explicit package name (did you forget to declare "my $mon月"?) at D:\test\test2.pl line 8. Global symbol "$mday日" requires explicit package name (did you forget to declare "my $mday日"?) at D:\test\test2.pl line 8. Global symbol "$hour時" requires explicit package name (did you forget to declare "my $hour時"?) at D:\test\test2.pl line 8. Global symbol "$min分" requires explicit package name (did you forget to declare "my $min分"?) at D:\test\test2.pl line 8. Global symbol "$sec秒" requires explicit package name (did you forget to declare "my $sec秒"?) at D:\test\test2.pl line 8. Execution of D:\test\test2.pl aborted due to compilation errors. ----------------------------------------------------- 実行結果 NG (PC2 Windows7 ActivePerl) Malformed UTF-8 character (unexpected continuation byte 0x94, with no precedingstart byte) at C:\test\test2.pl line 8. (略) Malformed UTF-8 character (unexpected continuation byte 0x95, with no precedingstart byte) at C:\test\test2.pl line 8. 2018 N12 26 9 5 4 b ----------------------------------------------------- 期待している実行結果 2018年12月26日 9時36分6秒 ----------------------------------------------------- よろしくお願いします。

  • Perl
  • 回答数3
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
  • maiko04
  • ベストアンサー率17% (345/1956)
回答No.3

#!C:/perl/bin/perl use strict; use utf8; use Encode; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year += 1900; $mon += 1; my $string=$year."年".$mon."月".$mday."日 ".$hour."時".$min."分".$sec."秒\n"; print encode('cp932', $string); 実行結果 2018年12月26日 11時41分43秒 $year年 という変数名だと思っているのでしょう。

yam2012
質問者

お礼

この方法は質問する前に試していたのですが その時はうまくいきませんでした。 しかし、今、実行してみると エラーは出ず日本語が正しく表示されています。 最初、この原因がよく分からなかったのですが、 上記のコードを、No2の回答者様の回答のように、 「Shift+JIS」で保存するとエラーになり、 「UTF8」で保存すると日本語が正しく表示される ことがわかりました。 つまり、「UTF8」で保存しておかなければならない問題と、 変数名の後に日本語が続くと、変数名と日本語の全体が 1つの変数として解釈されてしまう問題の 2つの問題があったようです。 ありがとうございました。

その他の回答 (2)

  • chie65535
  • ベストアンサー率43% (8522/19371)
回答No.2

>どのようにすればよいでしょうか。 use utf8のプラグマは「プログラムのソースコード内の文字列の漢字はUTF8で記述されてますよ」というプラグマです。 なのでuse utf8と宣言したソースコードは「UTF8で保存」しないとならない。 もし、ソースコードをシフトJISやEUCで記述・保存してあるのであれば my $string="$year年$mon月$mday日 $hour時$min分$sec秒\n"; の行の「年」や「月」や「日」などの漢字部分は「UTF8の漢字コードじゃないのが理由で正しく解釈できない」ので、エラーになります。 test2.plを「UTF8」で保存して、実行してみて下さい。

yam2012
質問者

お礼

回答ありがとうございます。 その前に一部訂正があります。 No.1の回答者様の補足コメント入力欄に書いてありますので ご確認ください。 > test2.plを「UTF8」で保存して、実行してみて下さい。 test2.plを「UTF8」で保存して実行してみました。 コマンドプロンプトに直接表示した場合は、 日本語の部分が文字化けしていますが、 リダイレクト(perl test2.pl > test.txt 2>&1)すると UTF8形式のファイルが生成されて文字化けはしていませんが、 結果は変更前と同じ(NG)でした。 print $string; print encode('utf-8', $string); print encode('cp932', $string); どれも変更前と同じ結果(NG)になります。 よろしくお願いします。

  • maiko04
  • ベストアンサー率17% (345/1956)
回答No.1

encode('Shift_JIS', $string); でどうですか?

yam2012
質問者

お礼

回答ありがとうございます。 encode('Shift_JIS', $string); にして実行してみましたが全く同じ結果(NG)になります。 よろしくお願いします。

yam2012
質問者

補足

一部訂正があります。 「print $string;」のPC1の実行結果のみが、 今、実行してみると、以下のようになっていました。 -------------------------------------- Passing malformed UTF-8 to "_Perl_IDCont" is deprecated at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDStart" is deprecated at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected continuation byte 0x94, with no preceding start byte) at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDCont" is deprecated at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDStart" is deprecated at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected continuation byte 0x8c, with no preceding start byte) at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected continuation byte 0x8e, with no preceding start byte) at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDCont" is deprecated at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDStart" is deprecated at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected continuation byte 0x93, with no preceding start byte) at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected non-continuation byte 0x20, immediately after start byte 0xfa) at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDCont" is deprecated at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDStart" is deprecated at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected continuation byte 0x8e, with no preceding start byte) at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected continuation byte 0x9e, with no preceding start byte) at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDCont" is deprecated at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDStart" is deprecated at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected continuation byte 0x95, with no preceding start byte) at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected continuation byte 0xaa, with no preceding start byte) at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDCont" is deprecated at D:\test\test2.pl line 8. Passing malformed UTF-8 to "_Perl_IDStart" is deprecated at D:\test\test2.pl line 8. Malformed UTF-8 character (unexpected continuation byte 0x95, with no preceding start byte) at D:\test\test2.pl line 8. 2018 N12 26 11 58 34 b -------------------------------------- よろしくお願いします。

関連するQ&A

  • use strict;

    Global symbol "@exec_test_list" requires explicit package name at ./ctest.pl line 384. Global symbol "@exec_test_no" requires explicit package name at ./ctest.pl line 384. Global symbol "@protocol_list" requires explicit package name at ./ctest.pl line 397. Global symbol "@protocol_list" requires explicit package name at ./ctest.pl line 406. Global symbol "$name" requires explicit package name at ./ctest.pl line 413. use strict;を書くと以上のようなエラーメッセージが 出力されます。どうしたら、以上のようなエラーを 回避できるでしょうか?教えてください。

    • ベストアンサー
    • Perl
  • Perlでの Timeの足し算

    時間の足し算をやりたい。訳あってライブラリが使えません。 方法は無いでしょうか? 仮にライブラリが使えるなら、下記のようでうまく行っています。 --------------------------------------------------- use Time::Local; $year=2008; $mon =10; $mday=24; $hours = 23; $min = 0; $sec = 0; $time = timelocal($sec, $min, $hours, $mday, $mon - 1, $year); $a1=($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time ); $mytimeORG= sprintf("%04d/%02d/%02d %2d:%2d", $year + 1900, $mon +1, $mday,$hour,$min); print "$mytimeORG\n"; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time + 32400); #9H加算 $mytime9H= sprintf("%04d/%02d/%02d %02d:%02d", $year + 1900, $mon +1, $mday,$hour,$min); print "$mytime9H\n"; ---------------------------------------------

    • ベストアンサー
    • Perl
  • 先月(YYYYMM)の生成方法

    言語は問いません。 先月をYYYYMM形式の文字列で得るクールな方法ってありますか? Perlで以下のように書けば正しく動きますが、なんかダサイ気がします。 my ($sec, $min, $hour, $mday, $mon, $year) = localtime ; $year -= 1 if $mon == 0; $mon = '12' if $mon == 0; $yearmonth = sprintf("%4d%02d", $year+1900, $mon); よろしくお願いします。

  • perl 5.8.8 日本語マッチ

    perl5.8.8を使っています。 日本語にマッチする正規表現を書きたいのですが、どうしてもマッチしません。 例えば、以下のファイルtest.txtから「さしすせそ」だけを抽出し、表示させたいです。 ---------test.txt-------------------------------- あいうえお かきくけこ さしすせそ たちつてと -------------------------------------------------- ----------test.pl-------------------------------- use strict; use warnings; open(FILE, 'test.txt') or die "$!"; my @file = <FILE>; close(FILE); foreach my $line (@file){ if($line =~ /^さ/){ print "$line\n"; } } ------------------------------------------------ このtest.plを実行しても「さしすせそ」を抽出することが できません。 どうしたらよいのでしょうか? 自宅の新しいバージョンのperlだとできるのですが 会社のperlは5.8.8で顧客環境でもあるのでバージョンアップも できません。 すみませんが、よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • Perlの日付取得で月の表示がおかしい

    下記は、メールフォームCGIに書き込まれた日時などの情報をlog.cgiというファイルに書き出すスクリプトです。 2012/01/04 21:05:45 のような感じで、日付が刻まれるのですが、このうち月の部分がどの月に処理を行ってもいつも01になってしまうのですが、当方直し方がわかりません。 下記が実際の記載箇所です。4行目がおかしいのだと思いますが、どなたかお分かりの方、教えていただけないでしょうか。 my $path = "log.cgi"; my $ip = $ENV{'REMOTE_ADDR'}; ($sec, $min, $hour, $mday, $month, $year, $wday, $stime) = localtime(time()); my $time = sprintf("%04d\/%02d\/%02d %02d\:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec); my $message = $in{'メッセージ'}; $message =~ s/\r\n/ /g; $message =~ s/\n/ /g; if (open(FOUT, ">> $path")) { print FOUT "$time\t$ip\t" . $in{'お名前'} . "\t" . $in{'E-mail'} . "\t" . $message . "\r\n"; close(FOUT); } よろしくおねがいいたします。

    • ベストアンサー
    • Perl
  • localtimeについて

    まだCGIを勉強はじめのなのですが、localtimeについて質問させてください。 書籍で時間取得には ($sec,$min,$hour,$mday,$mon,$year,$wno) = localtime(time); とし、time関数で得たものをlocaltime関数で整形 といった事が書かれています。 まずわからないのが最初の ($sec,$min,$hour,$mday,$mon,$year,$wno) = の部分なのですが、カッコ内に変数を並べるというのはどういった命令なのでしょうか?書籍ではここまででこのような使い方や記述は出てきていないので、それ自体がよく理解できずにいます。それとも($sec,$min,$hour,$mday,$mon,$year,$wno) = localtime(time);をおきまりパターンとしてワンセットで覚えるべき事なのでしょうか。 続いてlocaltime(time)ですが、これは()内のtime関数によって取得された1970年基準からの秒数を、localtimeによって英語圏での標準的な日付時間表記に直して表示するという事で良いのですよね? これが、なぜ ($sec,$min,$hour,$mday,$mon,$year,$wno) とすることで各変数に割り振ることができるのかがよく分かりません。 これらはおきまりパターンとして覚えるべき事なのでしょうか?それとも配列のようにあるパターンに乗っ取って書かれ得いる事で他に応用がきくような意味合いのものなのでしょうか? ご教授いただきたく思います。 よろしくお願いします。

    • 締切済み
    • CGI
  • 日付求め

    お世話になります。 早速ですが、perlで以下のように 現在時刻を求め表示するロジックがあります。 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); $year=$year + 1900; $mon =$mon + 1; $date81 = "$year年$mon月$mday日($days[$wday])"; $date82 = "$hour時$min分$sec秒"; この時、 例えば今年末であれば、 2009年1月1日0時と表示されると思います。 これを2008年12月31日24時と表示したいのですが、 何か妙案はあるでしょうか。 宜しくお願いします。

    • ベストアンサー
    • Perl
  • PerlからPHPへ移行 Part2

    以下、Perlのソースですが、これをコメントどおりに PHPに直すとどうなりますか? Time::Localは ppm install Time-Localでインストールできます。 use strict; BEGIN{ # BEGINはPHPで $|=1; # バッファリングしない } use Time::Local; #PHPでUseは? sub test_date_time{ my ($year, $mon, $mday, $hours, $min, $sec) = @_; # 可変引数な方法 my $serial = timelocal($sec, $min, $hours, $mday, $mon - 1, $year); my $moji = sprintf("$year年$mon月$mday日 $hours時$min分$sec秒"); return ($serial, $moji); # 複数の戻り値で様々な型で返す方法 } my ($serial, $moji) = test_date_time(2006, 10, 2, 10, 25, 30); # 一度に受け取る方法 print q{シリアルは} . $serial . "\n"; #q print qq{文字列は$moji\n}; my $ptn = qr{^(.+?)年(.+?)月(.+?)日\s(.+?)時(.+?)分(.+?)秒$}; if($moji =~ /$ptn/i){ print "$1/$2/$3 $4:$5:$6\n"; } exit(0); # 結果 #シリアルは1159752330 #文字列は2006年10月2日 10時25分30秒 #2006/10/2 10:25:30

    • ベストアンサー
    • PHP
  • Perlで日付を取得する

    Perlで日付を取得する perlで1週間分の日付を取得し、セレクトボックスに格納したいと思っています。 なるべくいま使っているサブルーチンを使いたいです。 # 現在日時を文字列化する sub get_date_string { # local(@week) = ("日", "月", "火", "水", "木", "金", "土"); local(@week) = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"); local($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime(time); $year += 1900; $mon++; # 文字列化する if ($hour < 10) { $hour = "0$hour"; } if ($min < 10) { $min = "0$min"; } if ($sec < 10) { $sec = "0$sec"; } $weekstr = $week[$weekday]; return "$year-$mon-$day ($weekstr) $hour:$min"; # return "$year年$mon月$day日 ($weekstr) $hour時$min分$sec秒"; } これを別のルーチンで、 $today = substr(&get_date_string,0,10); $kinou = $today - 1; $ototoi = $today - 2; として、今日の日付だけでなく、昨日、おととい、その前の日を取得したいと試みましたが、今日は取得できても、$kinouや$ototoiは、すごい数字になってしまいます。 変わりに -24*3600と引いてみましたがダメでした。 文字列に変更されていないから引けないのでしょうか? かんたんに処理できそうでできないので、詳しいやり方を教えてください。

    • ベストアンサー
    • Perl
  • localtime()での時間差の計算の仕方

    $ENV{'TZ'} = "JST-9"; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); my $now =sprintf("%04d/%02d/%02d-%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min); とすると 2007/01/28-15:56 のようにデータとして取得できるのですが・・・ これと登録日($date=2006/12/31-12:25)との日数差の計算ができません $now-$date とすると年数のところしか計算できず1としか表示できません 登録7日後以降にイベントを発生させたいのですが計算ができないのでうまくいきません 両方time()でやれば$now-$date>604800 とすればなんとかできるのですが登録日は『2006/12/31-12:25』の形で使いたいのです 登録日と現在の日数の差の計算方法を教えてくださいm(--)m

    • ベストアンサー
    • CGI

専門家に質問してみよう