『ボヘミアン・ラプソディ』はなぜ人々を魅了したのか >>

英語と日本語が交ざっているテキストから日本語部分を抽出するプログラムを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);
---

これを実行したところ、日本語も英語も書き出されず、数字だけ書き出されてしまいました。

日本語部分だけを抽出するようにするにはどのようにすれば良いでしょうか。
ご教示願います。

このQ&Aに関連する最新のQ&A

A 回答 (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]になります。)
    • good
    • 0

補足です。


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

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);
}

---

ありがとうございました。

お礼日時:2004/11/02 11:56

EUCならShift-JISより簡単かな?


半角カナとかが無いなら

while ・・・
{
  if ($c >= \x80) {
      #0x80以上はEUCの漢字コードとみなす
      print OUTPUTFILE $c;
  }
}

で、いかがでしょう?
本当は1行ずつ読んで正規表現使って処理するのが良いのですが。
(Ethersky様ご紹介のURLが参考になるかと。)

ちなみにこのプログラムだと漢字コードは出力しますが改行とかスペースとかは一切出力されませんのであしからず。
    • good
    • 0
この回答へのお礼

spinach-chickenさん

ありがとうございます。

今回はEtherskyさんの方法で処理することにします。
当初は1文字づつ判定と思ってたのですが、今回の目的には不適と思い至ったので。

Perl暦がまだ浅いのでそこら辺の判断もうまくできませんでした。失礼。m(_ _)m

お礼日時:2004/11/02 11:59

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

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で記述されたテキストから日本語(=全角部分)を抽出して別ファイルへ書き込む」
ということを考えてます。

よろしくお願いいたします。

補足日時:2004/11/01 13:23
    • good
    • 0

そのテキスト中の日本語の文字コードは何でしょうか?


それさえ分かっていれば正規表現で抜き出せます。

以下を参照してください。
http://www.din.or.jp/~ohzaki/perl.htm#Character

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

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q「WORD」での作業 日本語・英語混じりから日本語だけ削除

仕事上で、日本語の覚え書きなどを英訳する際、習慣として「パラグラフ毎」に「英訳文」を「日本語部分」の後に追加しています。

さて出来上がった後、「日本語部分だけ」を削除して「英語だけ」の文書に仕上げたいのですが。。。。

手作業で、1・2ページ位ならなんて事無いのですが、ページ数が多くなると時間ばかり掛かってしまいます。

「日本語部分だけ」を検索して「削除」なんて「離れ業」有りますでしょうか?

「削除後」に文書の校正が崩れてしまいますが、それは構いません。

Aベストアンサー

> 「ハイフォン」は「全角」「半角」どちらでしょうか?

「半角」です。

> 半角で入れてみましたが「結果何も起こりませんでした」

半角大カッコも必要ですよ。

> 「熙」or「黒の異体字」は何を意味するのでしょうか?

[ワイルドカードを使用する]がONの場合、[ -熙]は、
「 」から「熙」までの文字を表す特別な記述になります。

「 」(0x8140)が全角文字の最初の文字、
「熙」(0xeaa4)が漢字2(第2水準漢字)の最後の文字、
「黒の異体字」(0xfc4b)が漢字3(拡張文字コード)の
最後の文字です。
[IMEパッド]-[文字一覧]を開くと、参考になると、思います。

[ -黒](実際には「黒の異体字」)を使用されるといいでしょう。
「黒の異体字」は[IMEパッド-文字一覧]から入力してください。

Qエクセルマクロで日本語を抽出して転記する方法

お世話になります。
 
 単一セル内に英文+訳文といったデータがある場合に、同一行の隣のセルに訳文のみ転記するマクロを教えていただきたいのですが。完成形としては、当初のセルに英文のみ、右隣のセルに訳文のみといったものを想定しています。
 
 マクロが組めなければ関数でと考えましたが、データが大量になると自動計算が不可避で(たとえば手動計算にしても保存時等)時間がかかることから、マクロでと考えました。
 
 マクロは初心者ですが、簡単なものでしたら組めますが(今回も、ダブルクリック対応とか、()内の文字列を削除するとかはできました>)、抽出がうまく行きません。
 
 お手数をおかけしますが、よろしくご教示下さい。

Aベストアンサー

No.2です。

投稿後もう一度質問文を読み返してみると
>完成形としては、当初のセルに英文のみ、右隣のセルに訳文のみといったものを・・・

とありましたので、前回のコードは英字関係のみを抽出するだけでした。
ご希望の方法ではなかったと思いますので、もう一度顔を出しました。

B列に英字関係・C列に日本語を!という感じです。
尚、日本語を抽出するとなるとかなり、条件が多くなってしまいます。
第一水準・第二水準漢字・ひらがな・カタカナ・「ぁぃぅぇぉっゎ」等の促音
「が行・ざ行・・・」等々の濁音などに対応すると大変なので、前回のB列以外をC列にまとめるコードにしてみました。

Sub test() 'この行から
Dim i, k As Long
Dim str, buf1, buf2 As String
For i = 1 To Cells(Rows.Count, 1).End(xlUp).Row
For k = 1 To Len(Cells(i, 1))
str = Mid(Cells(i, 1), k, 1)
If str Like "[A-z 0-9 . , ! ? ]" Then
buf1 = buf1 & str
Else
buf2 = buf2 & str
End If
Next k
Cells(i, 2) = buf1
Cells(i, 3) = buf2
buf1 = ""
buf2 = ""
Next i
End Sub 'この行まで

これでC列にB列に表示されている文字以外が表示されると思います。

尚、確認の意味で敢えてA列はそのまま残しています。
A列削除は簡単だと思いますので・・・

何度も失礼しました。m(_ _)m

No.2です。

投稿後もう一度質問文を読み返してみると
>完成形としては、当初のセルに英文のみ、右隣のセルに訳文のみといったものを・・・

とありましたので、前回のコードは英字関係のみを抽出するだけでした。
ご希望の方法ではなかったと思いますので、もう一度顔を出しました。

B列に英字関係・C列に日本語を!という感じです。
尚、日本語を抽出するとなるとかなり、条件が多くなってしまいます。
第一水準・第二水準漢字・ひらがな・カタカナ・「ぁぃぅぇぉっゎ」等の促音
「が行・ざ行・・・」等々の濁...続きを読む

Q全角・半角混在の文字列から半角文字のみ取り出す

エクセル勉強中です。問題集で理解できないところがあります。
数式がどういう意味をもつのか教えて頂けるとありがたいです。
よろしくお願いします。

画像添付の問題になります。
A列に製品名が入っています。(製品番号:半角文字)(製品名:全角文字)
B列に半角文字の製品番号だけを取り出しなさいというものです。
半角文字の開始位置がバラバラになっているところが問題のポイントになっています。

回答ですが
B2:
=MID(A2,MATCH(1,INDEX(LENB(MID(A2,COLUMN(2:2),1))*1,0),),LEN(A2)*2-LENB(A2))
こちらで半角文字のみ取り出せるようです。回答には数式のみで何故この関数を使うのか?
使うことでどういった結果を導くなどの解説が一切ありません。(ちなみに出版会社の便利技的な問題集です)

MID関数で製品名A2から開始位置を指定して、全角半角をLEN関数LENB関数で半角文字数を
算出して文字列を抽出するという事は理解できます。
ただ、この開始位置の指定の所が理解できません。
数式を分割してみましたが
=MID(A2,COLUMN(2:2),1)の所はどの行も製品名の1文字目ですよね・・・
その値にLENB関数で文字数?
数式の検証で見てみると配列のような結果が次々と現れて・・・
MATCH関数もありますしINDEX関数が何か関係しているような気はしているのですが、
INDEX関数と言えば配列に行番号・列番号と例えば表の該当するセルの位置抽出の
知識しかありません。一つのセルでINDEX関数?

すいません。独学で勉強していてこの程度の知識ですが、この数式の考え方教えてくださる方よろしくお願いします。

エクセル勉強中です。問題集で理解できないところがあります。
数式がどういう意味をもつのか教えて頂けるとありがたいです。
よろしくお願いします。

画像添付の問題になります。
A列に製品名が入っています。(製品番号:半角文字)(製品名:全角文字)
B列に半角文字の製品番号だけを取り出しなさいというものです。
半角文字の開始位置がバラバラになっているところが問題のポイントになっています。

回答ですが
B2:
=MID(A2,MATCH(1,INDEX(LENB(MID(A2,COLUMN(2:2),1))*1,0),),LEN(A2)*2-LENB(A2))
こち...続きを読む

Aベストアンサー

ご質問のような半角文字を抽出するなら、提示された数式は一部非効率でわかりにくいところがありますが、個人的には最も簡単な配列数式になっていると思いますので参考までに検証方法を補足します。

まずB2セルに以下の式を入力してください(半角文字が11文字目までに出現する場合)。

=MID(A2,MATCH(1,INDEX(LENB(MID(A2,COLUMN(A:K),1)),0),),LEN(A2)*2-LENB(A2))

COLUMN関数の部分はROW関数で以下のようにするほうが数式がわかりよいかもしれません。

=MID(A2,MATCH(1,INDEX(LENB(MID(A2,ROW($1:$11),1)),0),),LEN(A2)*2-LENB(A2))

この画面上部の数式バーの数式のCOLUMN(A:K)(またはROW($1:$11))の部分をドラッグして選択しF9キーを押すと,「{1,2,3,4,5,6,7,8,9,10,11}」と表示されます(Escで解除)。

次に、MID(A2,COLUMN(A:K),1)の部分を選択し、F9キーを押すと、「{"お","徳","用","M","G","0","5","K","R","カ","ラ"}」とA2セルの先頭から11文字目までの文字が取得できていることがわかります。

次に、LENB(MID(A2,ROW($1:$11),1))の部分を選択し(INDEXを含む部分はこの配列を範囲に変換しているだけですので、この部分を省略するならCtrl+Shift+Enterで確定する必要があります)、F9キーを押すと、「{2,2,2,1,1,1,1,1,1,2,2}」のように、それぞれの文字の半角、全角が1と2で表示されます。

次にMATCH(1,INDEX(LENB(MID(A2,ROW($1:$11),1)),0),)の部分はMATCH関数(第三引数が0または省略)で1(=半角文字)が最初に出現する場所を調べています(上記の例なら4番目)。

ご質問のような半角文字を抽出するなら、提示された数式は一部非効率でわかりにくいところがありますが、個人的には最も簡単な配列数式になっていると思いますので参考までに検証方法を補足します。

まずB2セルに以下の式を入力してください(半角文字が11文字目までに出現する場合)。

=MID(A2,MATCH(1,INDEX(LENB(MID(A2,COLUMN(A:K),1)),0),),LEN(A2)*2-LENB(A2))

COLUMN関数の部分はROW関数で以下のようにするほうが数式がわかりよいかもしれません。

=MID(A2,MATCH(1,INDEX(LENB(MID(A2,ROW($1:$11),1))...続きを読む


人気Q&Aランキング