プロが教えるわが家の防犯対策術!

こんにちは、Perl始めて3か月ほどの大学生です。よろしくお願いします。

Perlにおいて「あいうえお」という文字列があればそれを配列に分けて入れることが最終目標です。
C言語出身なのでPerlにおける配列の概念がよくわからないのですが
$word[0]に「あ」、$word[1]に「い」となるように
もしくは@word[0][0]に「あ」、@word[0][1]に「い」となるようにしたいのです

自分なりに調べてみて
$lineに「abcde」が入っているとすると
my @word;
$word[0] = substr($line,0,1);とした場合
print $word[0]."\n";
はうまく「a」を出力することができました
しかし
$line = 'あいうえお';
とすると空白になってしまいました。

したがって
@word = spline(/ /,$line);
foreach(@word){ print $_."\n"; }
を試しました
出力結果は
abcde
とどうもうまく分けられていないようでした。

環境はよくわからないのですが
WindowsXPでputtyjp.exeというものを使ってサーバーにアクセスしていて
サーバーはLinuxのRedHatでした
日本語コードは[euc]になっていました
use uft8; をすると出力時に文字化けを起こします。

手詰まりになってしまいました。解決の糸口となるヒントがあれば教えて下さい。
2バイトごとに無理やり区切ることも考えましたがバイトごとに区切る方法が分からないのとアルファベットは1バイトのような気がするのでやり方がわからなくなっています。

ご指導のほど、よろしくお願いします。

A 回答 (4件)

use encoding は一見便利に見えるけど、落とし穴がそこらじゅうにあるのでお勧めしなかったんですがね。



ドキュメントを見ると
USAGE
use encoding [*ENCNAME*] ;
Sets the script encoding to *ENCNAME*. And unless ${^UNICODE} exist
and non-zero, PerlIO layers of STDIN and STDOUT are set to
":encoding(*ENCNAME*)".

Note that STDERR WILL NOT be changed.

Also note that non-STD file handles remain unaffected. Use "use
open" or "binmode" to change layers of those.

という部分があります。
つまり、open で開いたファイルから取ってきた内容についてはそのままでは
use encoding の影響は及びません。
open するときにそのファイルのエンコーディングを指定するか、
binmode でopen 後のファイルハンドルに対して指定します。

#!/usr/bin/perl
use strict;
use warnings;
use Jcode;
use encoding 'euc-jp';

open my $fh, '<:encoding(euc-jp)', 'sample02.txt' or die "Cannnot open sample02.txt : $!"; #分割する文書の取得
my $line = <$fh>;
close $fh;

print Jcode::getcode($line), "\n";
print join("\n", split(//, $lines));

実行結果:
utf8


















W
e
b

O
K
    • good
    • 0
この回答へのお礼

ご意見ありがとうございます!!
あいかわらずコードがasciiですが結果としてうまく出力することができました!
http://www.rwds.net/kuroita/program/Perl_unicode …
で調べたのですが、どうもUTF8フラグが原因であってますか?
use encodingは落とし穴もあるというアドバイスをいただけたので使わずにやってみました。
フラグについてもお聞きしたのですがずるずるなりそうなのでまた新たに質問を投稿させてもらおうと思います。
今後とも、アドバイスしていただけたら幸いです。

最終ソースコード
**************
use strict;
use Jcode;
use Encode;
#use utf8;
#use encoding 'euc-jp'; #なにしてるかわからない

binmode STDOUT, ':encoding(euc-jp)'; #STDOUTに入る文字列はeuc-jpにエンコードしてから入れるであってる?

my $lines;
my @word;

#ファイルオープン
open INTEXT, "<:encoding(euc-jp)", "sample02.txt"
or die "Cannnot open sample02.txt : $!"; #分割する文書の取得
#open my $fh, '<:encoding(euc-jp)', 'sample02.txt' or die "Cannnot open sample02.txt : $!"; #分割する文書の取得

#sample02.txt内容
#こんにちは。おひさしぶりです。これでWebもOK!
$lines = <INTEXT>;
#$lines = <$fh>;
#$lines = 'abcde';
#$lines = 'あいうえおかきくけこ';

my $code = &Jcode::getcode(\$lines);
print $code."\n";
#&Jcode::convert(\$lines, "euc", "$code" );
$code = &Jcode::getcode(\$lines);
print $code."\n";

#出力テスト
#print join(':',$lines)."\n";

@word = split(//,$lines);

#&Jcode::convert(\$word, "euc", "$code" );

foreach(@word){
print "$_\n";
}
*********************
出力
ascii
ascii


















W
e
b

O
K

お礼日時:2008/06/18 19:22

split するときに空白も入れないというのは#1の方のとおりで、


>use uft8; をすると出力時に文字化けを起こします。
これは出力のエンコーディングを指定してやればよいです。
こんな感じ。

use strict;
use warnings;
use utf8;

use feature ':5.10';
#use Encode qw/encode/;

binmode STDOUT, ':encoding(sjis)';

my $str_ascii = 'abcdefg';
my @chars = split q{}, $str_ascii;

say join(':', @chars);

my $str_kanji = 'こんにちは';
my @kchars = split q{}, $str_kanji;


#say join(':', map {Encode::encode('sjis', $_)} @kchars);
say join(':', @kchars);


binmode の行がそれです。eucを使っているのなら、'euc-jp' とかに
してみてください。
上記のスクリプトは5.10.0以降でないと動きませんので、5.8.xとかで
動かすのなら適当に修正してください。
#use feature の行を削る
#say を printに変えて、末尾を ,"\n"; にする

あ、あとスクリプト全体がutf-8でセーブされてないとだめです。

この回答への補足

申し訳ありませんが皆さんのを組み合わせたり試行錯誤しましたので一人一人に返事が書きづらくなったのでまとめて返事を書かせて下さい。

結論を言いますと、まだうまくいっていません。しかしかなり近いところまで行くことができました。ありがとうございます。
以下のソースでうまく出力することができました。

#!perl
use strict;
use warnings;
#use utf8;

#use feature ':5.10';
#use Encode qw/encode/;
use encoding 'euc-jp';

#binmode STDOUT, ':encoding(euc-jp)';

my $str_ascii = 'abcdefg';
my @chars = split q{}, $str_ascii;

print join(':', @chars)."\n";

my $str_kanji = 'こんにちは';
my @kchars = split q{}, $str_kanji;


#print join(':', map {Encode::encode('euc-jp',$_)} @kchars)."\n";
print join(':', @kchars)."\n";
************************
どうやら
use encoding 'euc-jp';
で解決したようです。

しかしファイルから読み込むと分けることはできたのですが。アルファベットと数字以外は表示されず空白で表示されるという状態が現状です。

$lines = 'あいうえお';
なのでJcodeを使ってコードを調べてみるとプログラム内で文字列を宣言した場合は
ascii
と表示されました。なぞです。
Jcodeでeucに無理やり変換させようとしましたがasciiのままでした。
しかし出力はうまく行きます。
ファイルから文字列を読み込んだ場合(日本語文字列)は、eucとなりました。
そして表示が空白となる現状です。
Jcodeで無理やりasciiにならないかと試しましたがeucのままでした。
もうさっぱりです。
申し訳ないですがもう少しソースを見ていただきたいです。
よろしくおねがいします。

********************
use strict;
use Jcode;
#use utf8;
use encoding 'euc-jp'; #なにしてるかわからない

#binmode STDOUT, ':encoding(euc-jp)'; #STDOUTに入る文字列はeuc-jpにエンコードしてから入れるであってる?

my $lines;
my @word;

#ファイルオープン
open INTEXT, "<sample02.txt"
or die "Cannnot create sample02.txt : $!"; #分割する文書の取得
#sample02.txt内容
#こんにちは。おひさしぶりです。これでWebもOK!
$lines = <INTEXT>;
#$lines = 'abcde';
#$lines = 'あいうえおかきくけこ';

my $code = &Jcode::getcode(\$lines);
print $code."\n";
&Jcode::convert(\$lines, "euc", "$code" );
$code = &Jcode::getcode(\$lines);
print $code."\n";

#出力テスト
print join(':',$lines)."\n";

@word = split(//,$lines);

foreach(@word){
print "$_\n";
}
********************

出力結果
euc
euc
こんにちは。おひさしぶりです。これでWebもOK!




































W
e
b


O
K


%

補足日時:2008/06/17 17:49
    • good
    • 0

バイト単位ではなく、文字単位で処理する必要があります。


その為には、Perl の内部文字列として扱う為に、
UTF8フラグを立てる必要があります。

また、UTF8 で書いて、use utf8 をした場合、
出力時には UTF8フラグを落とす必要があります。
(例) utf8::encode($result) # 引数が直接変化

# EUC-JP で書いた場合
use encoding 'euc-jp';
my $str = 'あいうえお';
my @result = split //, $str; # 1文字ずつなら split でも可
    • good
    • 0
この回答へのお礼

UTF8フラグ・・・いろいろ調べましたがやっぱりよくわかりません(笑)
結果的に
use encoding 'euc-jp';
でとりあえず動きました。ありがとうございます!!
またアドバイスいただけると幸いです。

お礼日時:2008/06/18 14:12

文字コードの問題はあるかもしれないけど, とりあえず


@word = split(//, $line);
を試してみる. // は間に空白も入れません.

この回答への補足

また今後もアドバイスを頂けると幸いです。

補足日時:2008/06/18 14:12
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます!!
空白を消したらうまく行きました!
どこかのHPに空白を入れると一文字ずつ区切られるという記述があったのですが(苦笑)
勘違いしていました。本当にありがとうございます!!

お礼日時:2008/06/18 14:09

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