ファイルの読み込みと出力
Perl初心者です。よろしくお願いします。
file.csvのようなファイルを読み込んで、
out.csvのように出力するプログラムを作成しているのですが
途中で変な改行が度々入っているためどうしてもうまくいきません。
(file.csvですが、実際は1500行以上あります。
また、最後に必ずendが入っています。
下記のcsvですがテキスト形式で表示した内容です。)
初歩的な質問で申し訳ありません。
調べる限り調べたのですが分かりませんでした。
どうかよろしくお願いします。
「file.csv」
"2010/1/1","C","こんにちは","田中","end",
"2009/10/2","B","おはよう","斉藤","end",
"2007/3/20","E","Good mor
ning","佐藤","end",
"1988/8/16","F","こんばんは","中
村","end",
"1999/1/10","A","Hello","木村","end",
"2005/9/17","D","おはようご
ざいます","斎藤","end",
「out.csv」(このように出力したいです)
C,こんにちは,田中,2010/1/1,end,
B,おはよう,斉藤,2009/10/2,end,
E,Good morning,佐藤,2007/3/20,end,
F,こんばんは,中村,1988/8/16,end,
A,Hello,木村,1999/1/10,end,
D,おはようございます,斎藤,2005/9/17,end,
「今書いているプログラムです」
#!/usr/local/bin/perl
use strict;
use Fatal qw/ open /;
my $csv_file = "file.csv";
my @csv = &readCsvFile($csv_file);
open(OUT,">out.csv");
for(my $i=0; $i<=5; $i++){
print OUT $csv[$i][1],",";
print OUT $csv[$i][2],",";
print OUT $csv[$i][3],",";
print OUT $csv[$i][0],",";
print OUT $csv[$i][4],",";
}
close(OUT);
sub readCsvFile {
open(DATA, $_[0]);
while(<DATA>) {
chomp;
push @csv, [ split(/",\"/) ];
}
close(DATA);
return @csv;
}
No.2ベストアンサー
- 回答日時:
気づいた点を直してみましたので、参考にしてください。
なお、ソースデータにクォートされた二重引用符がないことが条件になります。#!/usr/local/bin/perl
use strict;
use Fatal qw/ open /;
my $csv_file = "file.csv";
# my @csv = &readCsvFile($csv_file); # 代入は必要ない
my @csv;
&readCsvFile($csv_file);
open(OUT,">out.csv");
# for(my $i=0; $i<=5; $i++){
for(my $i=0; $i<=$#csv; $i++){ # 配列の要素数に合わせる
print OUT $csv[$i][1],",";
print OUT $csv[$i][2],",";
print OUT $csv[$i][3],",";
print OUT $csv[$i][0],",";
# print OUT $csv[$i][4],","; # 改行が必要
print OUT $csv[$i][4],",\n";
}
close(OUT);
sub readCsvFile {
# open(DATA, $_[0]); # DATA には特別な意味があるので好ましくない
open(IN, $_[0]);
my $line = "";
while(<IN>) {
chomp;
$line .= $_;
next if $line !~ /end/;
# push @csv, [ split(/",\"/) ];
push @csv, [ grep { length } split(/","|",|"/, $line) ]; # "," のみでは行頭や行末の " が残る
$line = "";
}
close(IN);
# return @csv;
}
回答していただきありがとうございました。
無事に解決できました!
要所々にコメントをいれていただきとても分り易かったです。
こうした問題をすぐに解決できるようにもっと勉強します。
ありがとうございました。
No.3
- 回答日時:
こんな感じでどうでしょうか?
条件としてご質問欄のようにデータは
・CSVはExcelのCSV形式(セル内に改行や記号が含まれる)
・データもプログラムもshift-jisコード(正規表現が誤動作する可能性があるのでEUCとかでやった方が・・・)
ただし「""」内のデータに「,」が含まれていると出力されたデータが再利用時に使い物にならない(別の文字に変換要)ので要注意
--------------------------------------------------------------------------------
#!/usr/local/bin/perl
use strict;
my $csv_file = "file.csv";
my @aDT = &readCsvFile($csv_file);## CSVファイルの読み込み
map { s/\r\n|\r|\n//g } @aDT;## 行内の改行を削除する
open(WR_DATA,">out.csv");
map { print WR_DATA $_."\n"; } @aDT;## 最近mapにはまってまして・・・「foreach(@aDT){ print WR_DATA $_."\n"; }」と同じです
close(WR_DATA);
exit;
sub readCsvFile {
my $sFN = shift;
my @aCSV;
open(RD_DATA, $sFN);
while(my $line = <RD_DATA>){
$line .= <RD_DATA> while ($line =~ tr/"// % 2 and !eof(RD_DATA));
$line =~ s/(?:\x0D\x0A|[\x0D\x0A])?$/,/;
my @aDT = map {/^"(.*)"$/s ? scalar($_ = $1, s/""/"/g, $_) : $_}
($line =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);## ?
## 元来この@aDTに各行の要素がいったん格納されますので個別に処理したいならここに処理を記述
my $sTmp = join(",",@aDT);## 各要素をコンマ区切りで結合して一行分を生成する
push(@aCSV,$sTmp);
}
close(RD_DATA);
return @aCSV;
}
--------------------------------------------------------------------------------
経験上の突っ込みどころとしては
・perlは行指向の言語なので多次元配列は避けるのが吉(やっていけないわけじゃないけど・・・)
・局所変数はしっかり定義(関数内の@csvは要注意)
・ファイルハンドル名や変数は、できるだけ予約語や組み込み関数名に類似した名前はさける
ご回答いただき、ありがとうございました。
> CSVはExcelのCSV形式(セル内に改行や記号が含まれる)
説明不足で申し訳ございませんでした。
ExcelのCSV形式のため変に改行が入ってしまい四苦八苦していました。
ちなみにデータとプログラムですがEUCで行っています。
> ただし「""」内のデータに「,」が含まれていると出力されたデータが
> 再利用時に使い物にならない(別の文字に変換要)ので要注意
まさにその通りです!
データ内に「,」がたくさん入っているため別の文字に変換をして処理をしていました。
mapの使い方に目から鱗です!
とても参考になります!
また、経験に基づいたアドバイスもとても参考になりました。
Perlをもっと勉強しないといけないと思いました。
本当にありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 複数csvを横に追加していくマクロについて 2 2023/04/25 09:19
- Excel(エクセル) 【マクロ】webアドレスにて指定されたCSVファイル【excelソフト表示】を印刷する件 1 2023/02/15 01:52
- Visual Basic(VBA) エクセルVBAについて 8 2022/07/13 22:41
- Visual Basic(VBA) 複数のcsvファイルをExcelに一括変換したい 2 2023/03/03 12:44
- Visual Basic(VBA) フォルダの場所を可変にしたいです(マクロ) 4 2023/05/11 10:00
- その他(プログラミング・Web制作) データ解析ソフトRでのファイル入力read.csvがエラーになります 7 2022/03/27 22:11
- CGI htmlからパラメータで、cgiに渡したい。 1 2023/02/06 16:15
- PHP 値の取り出し方について教えて下さい。 1 2023/03/31 13:30
- Excel(エクセル) エクセルのVBAについて とあるサイトのコードを参考に、CSVの文字化けを直すVBAを作成しているの 7 2022/11/04 14:15
- その他(プログラミング・Web制作) Fortranでの出力ファイル 2 2023/03/21 21:25
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
P.Cのシングルチューナーとダブ...
-
テキストファイルで提出とは?
-
Perlで、「が」を、「...
-
Perl LINE(チャット) 仕組み
-
Perlのエラーについてご教授く...
-
ファイルアイコンの左下に緑の□...
-
TeraPadエディターの操作方法に...
-
アルファベットに付いて質問し...
-
#!/usr/bin/perlで書きだしたCG...
-
perlのflock関数でロックをかけ...
-
AI sisterとは、偽物の人ですか?
-
bashスクリプト
-
perlプログラミング 空白行削除
-
perlでリテラル値はメモリにど...
-
perlで2次元配列をサブルーチ...
-
Perlで時間の計算
-
perlについて
-
perlのrequireの動き方について...
-
perlの構文でカンマの意味が分...
-
perlについての質問
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
テキストファイルで提出とは?
-
openした後、closeしないでプロ...
-
perlをバージョンアップしたら...
-
INDIRECT 横に再度抽出したい
-
Perl の外部モジュールの利用方法
-
Perlで特定文字列から特定文字...
-
Perlのエラーについてご教授く...
-
bashスクリプト
-
Strawberry Perl for Windows ...
-
perlで2次元配列をサブルーチ...
-
TeraPadエディターの操作方法に...
-
アルファベットに付いて質問し...
-
perlのflock関数でロックをかけ...
-
ファイルアイコンの左下に緑の□...
-
perlプログラミング 空白行削除
-
Wallpaper Engineでおすすめの...
-
Perlで時間の計算
-
perlのrequireの動き方について...
-
perlでリテラル値はメモリにど...
-
画像が表示でnull; this.src
おすすめ情報