- ベストアンサー
テキストファイルから日本語部分を抽出
英語と日本語が交ざっているテキストから日本語部分を抽出するプログラムをPerlで書きたいと思って以下のようなプログラムを組みました。 --- #!/usr/bin/perl print "Input file name: "; $ifname = <STDIN>; #print "Output file name: "; #$ofname = <STDIN>; $ofname = ">> tmp.txt"; open(INPUTFILE, $ifname); open(OUTPUTFILE, $ofname); while($c = getc(INPUTFILE)){ if('a'<= $c && $c <= 'z' || 'A'<= $c && $c <= 'Z'){ }else{ print OUTPUTFILE $c; } } close(INPUTFILE); close(OUTPUTFILE); --- これを実行したところ、日本語も英語も書き出されず、数字だけ書き出されてしまいました。 日本語部分だけを抽出するようにするにはどのようにすれば良いでしょうか。 ご教示願います。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
open(IN, "< euc.txt"); #対象ファイル open(OUT, "> euc.out.txt"); #出力ファイル while(<IN>){ tr/\x0D\x0A//d; #改行を一旦削る tr/[\x00-\x7F]//d; #1バイト文字除去 next if($_ eq ""); #空らな次の行へ print OUT "$_\n"; #書き出し } close(OUT); close(IN); 1バイト文字を全て消し去ることで2バイト文字が残るという方法です。(注:ファイルはEUCであることが前提。ShiftJISの場合は[\x00-\x7F\xA1-\xDF]になります。)
その他の回答 (5)
- Ethersky
- ベストアンサー率71% (168/235)
補足です。 書き忘れましたがNo.5の方法だと半角カナは残ります。 半角カナも除去したいのなら s/\x8E[\xA1-\xDF]//g; を追加してください。 (tr/\x8E[\xA1-\xDF]//d;だと文字化けします)
- spinach-chicken
- ベストアンサー率57% (24/42)
EUCならShift-JISより簡単かな? 半角カナとかが無いなら while ・・・ { if ($c >= \x80) { #0x80以上はEUCの漢字コードとみなす print OUTPUTFILE $c; } } で、いかがでしょう? 本当は1行ずつ読んで正規表現使って処理するのが良いのですが。 (Ethersky様ご紹介のURLが参考になるかと。) ちなみにこのプログラムだと漢字コードは出力しますが改行とかスペースとかは一切出力されませんのであしからず。
お礼
spinach-chickenさん ありがとうございます。 今回はEtherskyさんの方法で処理することにします。 当初は1文字づつ判定と思ってたのですが、今回の目的には不適と思い至ったので。 Perl暦がまだ浅いのでそこら辺の判断もうまくできませんでした。失礼。m(_ _)m
- spinach-chicken
- ベストアンサー率57% (24/42)
一番簡単なShift-JISのみ抽出するプログラムは以下のようなかんじでしょうか(適当ですが。getcをしているwhileの前後だけです。) #------------------------ #漢字かどうかのフラグ。 $flg = 0; while ・・・ { if ($flg == 1) { #漢字の2バイト目なのでそのまま出力 print OUTPUTFILE $c; $flg = 0; } else { if ($c >= \x80) { #0x80以上はShift-JISで全角文字の1バイト目とみなす $flg = 1; print OUTPUTFILE $c; } else { #漢字2バイト目以外の0x80以下の文字は英字とみなす。 } } }
- spinach-chicken
- ベストアンサー率57% (24/42)
if('a'<= $c && $c <= 'z' || 'A'<= $c && $c <= 'Z'){ なによりまず、これだと、 「aより大きくかつzより大きい」または「Aより大きくかつZより大きい」 ということで範囲がおかしいかと。 それから日本語は2バイトで表現されますが、文字コードがShiftJISの場合、漢字の文字コード中に、英語の文字コードが含まれるケースがあります。 (例:「イ」の文字コードは0x8343ですが、2バイト目の0x43は英字の「C」の文字コードです。 このプログラムを作る際は、 (1)日本語と英語を分離するファイルは、何の文字コード(Windowsなら普通Shift-JIS)で書かれているか。 (2)分離する英字はどの範囲か(半角全て(数字や記号を含む)か、アルファベット(A-Z)のみか) という情報が必要です。 そのあたりはいかがでしょうか?
補足
>spinach-chickenさn ありがとうございます。 (1)文字コードはEUC (2)悩ましいところですが、とりあえず半角すべてを分離しようと思ってます。 つまり、 「EUCで記述されたテキストから日本語(=全角部分)を抽出して別ファイルへ書き込む」 ということを考えてます。 よろしくお願いいたします。
- Ethersky
- ベストアンサー率71% (168/235)
そのテキスト中の日本語の文字コードは何でしょうか? それさえ分かっていれば正規表現で抜き出せます。 以下を参照してください。 http://www.din.or.jp/~ohzaki/perl.htm#Character
お礼
Etherskyさん、具体的にプログラムを書いていただいてありがとうございます。 おかげで基本的な部分はできてきたと思います。 フィードバックとして現在のコードを乗せておきます。 処理についてはEtherskyさんにご教示いただいた方法です。 それ以外にフォルダ内のファイル(.c, .h)を開き、それぞれのファイル名に.outを付け足して出力ファイルとする方法をとりました。 --- #!/usr/bin/perl #ディレクトリのオープン opendir (DIR,"./") ; @files = grep { /\.c$/ || /\.h$/ } readdir DIR; #@files = grep { /\.c$/} readdir DIR; close DIR; print "1" ; foreach $ifname (@files){ print "2" ; $ofname = "> ".$ifname.".out"; open(IN, $ifname ); #対象ファイル open(OUT, $ofname ); #出力ファイル while(<IN>){ tr/\x0D\x0A//d; #改行を一旦削る tr/[\x00-\x7F]//d; #1バイト文字除去 next if($_ eq ""); #空らな次の行へ print OUT "$_\n"; #書き出し } close(OUT); close(IN); } --- ありがとうございました。