• ベストアンサー

文字を一文字ずつ区切りたい

こんにちは、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バイトのような気がするのでやり方がわからなくなっています。 ご指導のほど、よろしくお願いします。

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

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.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 !

kiki28
質問者

お礼

ご意見ありがとうございます!! あいかわらずコードがasciiですが結果としてうまく出力することができました! http://www.rwds.net/kuroita/program/Perl_unicode.html で調べたのですが、どうも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 !

その他の回答 (3)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

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でセーブされてないとだめです。

kiki28
質問者

補足

申し訳ありませんが皆さんのを組み合わせたり試行錯誤しましたので一人一人に返事が書きづらくなったのでまとめて返事を書かせて下さい。 結論を言いますと、まだうまくいっていません。しかしかなり近いところまで行くことができました。ありがとうございます。 以下のソースでうまく出力することができました。 #!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 %

  • kodomo55
  • ベストアンサー率57% (8/14)
回答No.2

バイト単位ではなく、文字単位で処理する必要があります。 その為には、Perl の内部文字列として扱う為に、 UTF8フラグを立てる必要があります。 また、UTF8 で書いて、use utf8 をした場合、 出力時には UTF8フラグを落とす必要があります。 (例) utf8::encode($result) # 引数が直接変化 # EUC-JP で書いた場合 use encoding 'euc-jp'; my $str = 'あいうえお'; my @result = split //, $str; # 1文字ずつなら split でも可

kiki28
質問者

お礼

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

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

文字コードの問題はあるかもしれないけど, とりあえず @word = split(//, $line); を試してみる. // は間に空白も入れません.

kiki28
質問者

お礼

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

kiki28
質問者

補足

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