電子書籍の厳選無料作品が豊富!

現在1.5GB程のcsvファイルを処理しています
通常通りExcelやその他csvを開くソフトで開こうとしても
どうしても処理に膨大の時間がかかる一方で一部しか開けない現状です
そこでpealを用いて抽出をしようとしているのですが
うまく出来ないのが現状です


仮に花のデータがあったとします
花の種類としてはチューリップやあじさい10種類以上の花があり
色や花識別番号,花の数が別の列に数字として入力されています

  1行目が(空白),種類,色,花識別番号,花の数,実の数,枯れた花の数
  2行目が(空白),チューリップ,黄色,1,2,2,2
3行目が(空白),チューリップ,緑,2,4,2,2
...
  10行目が 3行目が(空白),あじさい,緑,2,4,2,2


...以下同様にあじさいなど他の花の種類も入力されているとします
このとき,花の名前と色と花識別番号を指定して
花の名前と色と花識別番号,花の数,実の数,枯れた花の数のデータを抽出をしたいのですが
どうしても1列目の花の種類しか指定ができず,2列目以降の色や花識別番号を指定することができません
仮にチューリップを抽出しようとする場合は

while(<STDIN>){
my @line = split(/,/, $_);
$cols = @line;
if($cols>1) {
if($line[1] eq "種類" ||
$line[1] eq "チューリップ"||
$line[2] eq"2" ||) {
print $_;
}
}
}

現状は…以上ののような形にて作成してます
しかし,これではうまくできませんでした

分かる方いらっしゃいましたら知恵を貸してください

A 回答 (4件)

こういうデータを持ったファイルがあるとして、それをflower.csvと名付けます。



name, color, id, num_of_flower, num_of_fruit, dead
tulip, yellow, 1, 2, 2, 2
tulip, green, 2, 4, 2, 2
rose, green, 2, 4, 2, 2

で以下のコードでこのファイルを読みこんで連想配列上にデータベースを作ってから、花の名前と色と識別番号をコロンでつなげて一つのキーとして連想配列に入力すれば所望の情報を得られます。

#!/usr/bin/perl

open(F, "flower.csv");

while(<F>){
chomp;
s/\s+//g;
@x = split(/,/, $_);
$key=$x[0].":".$x[1].":".$x[2];
$info{$key} = "$x[3] $x[4] $x[5]";
}

close(F);

print "=> ";
while(<>){
chomp;
print "$info{$_}\n";
print "=> ";
}


実行例

> ./foo
=> tulip:yellow:1
2 2 2
=> tulip:green:2
4 2 2
=> rose:green:2
4 2 2
=>
    • good
    • 0

>通常通りExcelやその他csvを開くソフトで開こうとしても


 CSVは、Comma-Separated Valuesの略でテキストファイルですから、Excelやその他CSVを開くソフトと言うのは間違いでしょう。テキストエディタで扱いましょう。
 例えば正規表現が扱えるEmエディタ( https://jp.emeditor.com/ )のようなテキストエディタでしたら、置換操作で
^((?!^,チューリップ,1234).)+\n

    ここは何も書かない。
で一致しない行は消し去ることができます。
 もっと早くしたければ、なんと言ったってSED( http://ja.wikipedia.org/wiki/Sed_%28%E3%82%B3%E3 … )です。1.5GB程度なら十数秒で終わる。SEDの資料はネット上にたくさんあるのでそれを参照

 Perl(pealじゃない)を使う場合は、大量に読み込むと危険なので
open(IN,"data.csv");
while(<IN>) {
正規表現処理で一致しない物をリスト@abcに格納
}
close(IN);
open(OU,"+> data2.txt");
while(<@abc>){
print OU $_;
}
close(OU);
    • good
    • 0

具体的に、どんな風に「うまくいかない」なのでしょうか?


「条件に一致しているはずなのに出てこない」

「条件に一致しないのに出てくる」

「エラーで動かない」
とでは、対処方法も違います。


( $line[1] eq "種類" ||
$line[1] eq "チューリップ"||
$line[2] eq"2" ||)

これが、どんな抽出をしようとして書いたのか、それが書いてないので、修正方法もわかりません。

このままだと、
 1列目が「種類」
  または
 1列目が「チューリップ」
  または
 2列目が「2」
  または ...で || の後に式が無いからエラー

最後の || が間違いだとすると、
$line[2] は 「色」なので、 「2」になることは無いと予想されます。
ですが、line[1] eq "チューリップ" が成立すれば、全体としてifの条件が成立します。

$line[3]の間違いだとすると
> 10行目が (空白),あじさい,緑,2,4,2,2
も$line[3] == 2 ですから、該当します。


確実にハマりそうなのは

while(<STDIN>){
my @line = split(/,/, $_);

<>で読み込んだ文字列には、改行文字まで含まれています。
そのままspitすると、最後の項目は
$line[7] = "2\n"
等としたのと同じになり、文字列で比較すると
"2" ne "2\n"
となります。

また、このsplitでは、前後の空白が残ります。CSVの書き方次第では
$line[3」ne "2" # line[3]=" 2 "になっている
等となる可能性もあります。

この回答への補足

このとき,花の名前と色と花識別番号を指定して
花の名前と色と花識別番号,花の数,実の数,枯れた花の数のデータを抽出をしたいのですが
どうしても1列目の花の種類しか指定ができず,2列目以降の色や花識別番号を指定することができません
仮にチューリップと花識別番号2番を抽出しようとする場合は
while(<STDIN>){
my @line = split(/,/, $_);
$cols = @line;
if($cols>1) {
if($line[1] eq "種類" ||
$line[1] eq "チューリップ"||
$line[2] eq"2" ||) {
print $_;
}
}
}

としました。結果としてチュウリップに該当するものはすべて抽出され
花識別番号は2番以外ののものも抽出されています
当該ファイルは動いているのですが,思ったように挙動していないのが現状です

補足日時:2015/01/12 16:30
    • good
    • 0

> 抽出をしようとしているのですが


別ファイルとしてもよければ、コマンドプロンプトで
FINDコマンドで絞り込みして、リダイレクト。

参考URLの中央あたり、「フィルタとしても利用可能」で
FINDにTXTファイル読ませ、表示してます。
画面出力を>で別ファイルにすることでサイズを小さくできます。
何度か条件を変えながら繰り返せば、EXCELでも読めるサイズになるかと。

参考URL:http://www.atmarkit.co.jp/ait/articles/0103/01/n …

この回答への補足

このとき,花の名前と色と花識別番号を指定して
花の名前と色と花識別番号,花の数,実の数,枯れた花の数のデータを抽出をしたいのですが
どうしても1列目の花の種類しか指定ができず,2列目以降の色や花識別番号を指定することができません
仮にチューリップと花識別番号2番を抽出しようとする場合は
while(<STDIN>){
my @line = split(/,/, $_);
$cols = @line;
if($cols>1) {
if($line[1] eq "種類" ||
$line[1] eq "チューリップ"||
$line[2] eq"2" ||) {
print $_;
}
}
}

としました。結果としてチュウリップに該当するものはすべて抽出され
花識別番号は2番以外ののものも抽出されています
当該ファイルは動いているのですが,思ったように挙動していないのが現状です

補足日時:2015/01/12 16:30
    • good
    • 0

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