• ベストアンサー

テキストファイルから日本語部分を抽出

英語と日本語が交ざっているテキストから日本語部分を抽出するプログラムを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); --- これを実行したところ、日本語も英語も書き出されず、数字だけ書き出されてしまいました。 日本語部分だけを抽出するようにするにはどのようにすれば良いでしょうか。 ご教示願います。

  • Yupa3
  • お礼率81% (91/112)
  • Perl
  • 回答数6
  • ありがとう数4

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

  • ベストアンサー
  • Ethersky
  • ベストアンサー率71% (168/235)
回答No.5

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.6

補足です。 書き忘れましたがNo.5の方法だと半角カナは残ります。 半角カナも除去したいのなら s/\x8E[\xA1-\xDF]//g; を追加してください。 (tr/\x8E[\xA1-\xDF]//d;だと文字化けします)

Yupa3
質問者

お礼

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); } --- ありがとうございました。

回答No.4

EUCならShift-JISより簡単かな? 半角カナとかが無いなら while ・・・ {   if ($c >= \x80) {       #0x80以上はEUCの漢字コードとみなす       print OUTPUTFILE $c;   } } で、いかがでしょう? 本当は1行ずつ読んで正規表現使って処理するのが良いのですが。 (Ethersky様ご紹介のURLが参考になるかと。) ちなみにこのプログラムだと漢字コードは出力しますが改行とかスペースとかは一切出力されませんのであしからず。

Yupa3
質問者

お礼

spinach-chickenさん ありがとうございます。 今回はEtherskyさんの方法で処理することにします。 当初は1文字づつ判定と思ってたのですが、今回の目的には不適と思い至ったので。 Perl暦がまだ浅いのでそこら辺の判断もうまくできませんでした。失礼。m(_ _)m

回答No.3

一番簡単な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以下の文字は英字とみなす。     }   } }

回答No.2

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)のみか) という情報が必要です。 そのあたりはいかがでしょうか?

Yupa3
質問者

補足

>spinach-chickenさn ありがとうございます。 (1)文字コードはEUC (2)悩ましいところですが、とりあえず半角すべてを分離しようと思ってます。 つまり、 「EUCで記述されたテキストから日本語(=全角部分)を抽出して別ファイルへ書き込む」 ということを考えてます。 よろしくお願いいたします。

  • Ethersky
  • ベストアンサー率71% (168/235)
回答No.1

そのテキスト中の日本語の文字コードは何でしょうか? それさえ分かっていれば正規表現で抜き出せます。 以下を参照してください。 http://www.din.or.jp/~ohzaki/perl.htm#Character

参考URL:
http://www.din.or.jp/~ohzaki/perl.htm#Character

関連するQ&A

  • テキストファイルから日本語部分を削除

    英語と日本語が交ざっているテキストから日本語部分を削除するプログラムをPerlで書きたいと思って以下のようなプログラムを組みましたが、うまくいきません。 while ( <IN> ) { chomp; tr/^[\x00-\x7f]//d; print OUT "$_\n"; } Perl初心者です。助けてください。

  • Perl ファイルハンドルを閉じずに反映させる

    お世話になっております。 Perl(プログラミング言語)について質問です。 openメソッドで開いたファイルハンドルに print文で書込みを行った際に、ファイルハンドルをcloseせずに、 書込みを反映させる方法はありますか? 開くのはファイルではなく(他プロセスへの)パイプです。 $| を設定してもだめでした (例としては perl1.pl , perl2.pl を用意する <perl1.pl> $i; open(OUT,"| perl2.pl") while(1){ print OUT "$i" $i++  } close(OUT) <perl2.pl> while( <STDIN> ) { print $_; } のようなことをやりたいです。 上記のようなスクリプトを実行したところ、 perl1のcloseが実行されるまで反映されません。 これをcloseをせずに反映させる方法はありますでしょうか? よろしくお願いします。

    • ベストアンサー
    • Perl
  • 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によるXMLファイルの解析&出力

    XMLファイルで以下のようなXMLファイルから、 <?xml version="1.0" encoding="Shift_JIS"?> <class3> <Personal> <No>1</No> <Name>相上男</Name> <phone>00-0000</phone> </Personal> <Personal> <No>2</No> <Name>柿句毛子</Name> <phone>11-1111</phone> </Personal> </class3> perlでNameの部分のタグだけ抜き出しXMLファイルに出力するプログラムを組み立てたいです。自分でも以下のようなプログラムを組み立てたのですが、 #!/usr/bin/perl use strict; use Encode; use XML::XPath; use XML::XPath::XMLParser; # 書き込み用にファイルを開く open( OUTPUTFILE, ">Output2.xml" ); # 標準出力に書き出し print &xml_xpath; # ファイルを出力先に設定 select( OUTPUTFILE ); # 出力先を元に戻す select( STDOUT ); # ファイルを閉じる close( OUTPUTFILE ); sub xml_xpath{ my $file = "class3.xml"; my $xp = XML::XPath->new(filename => $file); foreach my $node( $xp->find('/class3/Personal/Name')->get_nodelist){ print Encode::encode("shift_jis", $node )."\n"; } } XML::XPath::Node::Element=REF(0x1036c58c) XML::XPath::Node::Element=REF(0x1036cb8c) と、出てくるだけで動きません。ほとんど初心者なのでまったく見当違いのプログラムを組み立てているかもしれませんが、よろしくおねがいします。

  • Perlでテキストファイル読み込み

    基本的な質問ですみません。 サーバ上のテキストファイルを読み込んで ローカルのテキストファイルに書き込むというだけなのですが 何度やってもできません。 以下プログラムですが #!usr/bin/perl open(IN,"http://*****/***/***.txt"); $file = <IN>; close(IN); open(OUT,"> a.txt"); print(OUT "$file"); close(OUT); サーバのアドレスは、URLうってみて見れたのでhttp://***(以下略)であってると思います。 サーバのテキストにはchmodで777と権限を与えました。 プログラムに問題あるのでしょうか。 この場合考えられる原因を教えてください。

    • ベストアンサー
    • Perl
  • ファイルから読み込んだ文字を

    ファイルから読み込んだ全角文字をあるキーワード(例えば"田中")が含んでいるか否かを判定するプログラムをつくりたいのですが、なかなか上手くいきません。ファイルをopenし中の文字を読込み、それを変数に格納、ifでeq使って判定したのですが、全角は判定してくれません。全角を判定するには一体どうしたら良いのでしょうか? $filename = "####.txt"; open( $fh, "< $filename" ) #ファイルopen or die "Cannot open $file: $!"; $key = 'キ'; #キーワードを決めて while ($c = getc $fh ) { #比較する if($c eq $key){ print "キーワードを見付けました。"; } } close(fh); getcだとおそらく全角は文字コードを読み込んでしまうような感じでしょうか?print $c "\n";とすると文字化けします。しかし、printf("%d", $c);だと何も表示してくれません。これはord関数を使わねばならないのでしょうか?それとも別な方法が?等などためしたのですが、もう分かりません。 御指導御鞭撻をよろしくお願いします。

  • ファイルに書き込む

    二重に登録されないように既存ファイルを検索した後、ファイルに追記するプログラムを考えています。 次のプログラムを実行すると、二重登録されてしまいます。どうすれば、二重登録を防ぐ事ができるのでしょうか? #!c:/perl/bin/perl print "Content-type: text/html;\n\n"; require 'cgi-lib.pl'; &ReadParse(\%data); $name = $data{'name'}; $age = $data{'age'}; $sei = $data{'sei'}; $input = $name.$age.$sei; print "<HTML><HEAD>\n"; print "<TITLE>登録完了</TITLE>\n"; print "</HEAD><BODY>\n"; open(RF,"<mem.dat"); while($line=<RF>){ if($line eq $input){ print "既に登録されています。\n"; } } close(RF); open(FP,">>mem.dat"); print FP $input; print FP "\n"; close(FP); print "<H3>登録完了しました。</H3>"; print "</BODY></HTML>\n"; exit; 実行すると、二重登録されていても、必ず「登録完了しました。」と表示されてしまいます。

    • ベストアンサー
    • Perl
  • HTML形式のメールからテキストのみを抽出したい

    HTML形式の本文からHTMLのタグを除去して、プレーンテキストのみを抽出するプログラムを作成していますが、うまく処理ができなくて困っています。 使用言語はperl,HTML::Parserを使用してプログラムを作成したいと考えています。 日本語の本文のテキスト抽出を行っているのですが、 うまく抽出できるものと文字化けするものがあります。 nkfモジュールを使用すれば解決できそうだと考え、試行錯誤しておりますが、うまく処理できていません。 perlテキスト処理に詳しい方がいらっしゃいましたら、 教えてください。 よろしくお願いいたします。

  • Perlを使った正規表現について

    テキストファイルを読み込んで、以下のルールに従った文字列だけを.txtで出力するプログラムを書いています。 具体的にはテキストファイル中の "text":"★★★","to_user" で囲まれている★★★の部分のみを抽出したいです。 そこで正規表現に触りだしたのですが、表現がうまくいっていないようで1週間ほどはまっています。。うまく出力できるように直しをいただけないでしょうか。 打ち明けてしまうと、★★★の部分はtwitterの呟き(日本語)になります。 以下がそのソースになります。よろしくお願いします。 print "Input file name: "; $ifname = <STDIN>; open(IN, $ifname); open(OUT, "> out.txt"); #出力ファイル while(<IN>){ if($ifname =" m/"test":(.*?),"to_user"/; next if($_ eq ""); print OUT "$_\n"; #書き出し } close(OUT); close(IN);

    • ベストアンサー
    • Perl
  • テキストファイルの行抽出

    linux環境のプログラムについて質問です。 ある特定のファイル(テキストファイル)内のデータで 指定の行を抽出する方法を教えていただきたいと思います。 現在はawkを使用してbashスクリプト内で下記のように head, tailを使用していますが、処理が重いように 感じます。perlまたはawkなどで行抽出の軽い処理は できないでしょうか? (他のunixコマンドでも結構です。) ---------------------------------------- RNUM=`awk 'END{print NR}' $1` #行番号取得 for iwl in `seq 1 $RNUM`;do BASE=`head -n $iwl $1 | tail -n 1` done #iwl ---------------------------------------- Fortran, Cなども使えますが、色々組み合わせて使う上で bash内のスクリプトで行ないたいと思います。

専門家に質問してみよう