csvファイルを統合する方法

このQ&Aのポイント
  • あるディレクトリ内にある複数のcsvファイルを1つのファイルに統合する方法について説明します。
  • 指定したディレクトリ内にあるcsvファイルを1行ずつ読み込み、追加書き出しで1つのファイルに収める方法を解説します。
  • Perlを使用して指定したディレクトリ内にあるcsvファイルを統合する方法を説明します。
回答を見る
  • ベストアンサー

csvファイルを統合する

あるディレクトリにtest1.txtとtest2.txtというカンマ区切り(拡張子はcsvではないですけど)があったとして、それらのファイルを1行ずつ読み込み、それを追加書き出しで1つのファイルに収めていこうとしています。 そこで以下のようなコードを書いてみたのですが、どうやらtest1.txtしか読み込んで書き出せていないようなのです。その原因が分からずに困っています。 $dir = 'C:/Perl/workdir'; # 対象ディレクトリ名 open MYHANDLE, ">>out.txt"; # 追加書き出しモードでファイルハンドルをオープン opendir DH, $dir or die "$dir:$!"; # ディレクトリを開く while ($file = readdir DH) { # ディレクトリにあるファイル名を取得し、$fileに格納 next if $file =~ /^\.{1,2}$/; # '.'や'..'も取れるので、スキップする open MYFILE, "$file"; # 取得したファイルを開く while (<MYFILE>) { chomp; @dat = split /,/; # 読み込むファイルは「カンマ区切り」としてレコードを読み込む。 $n = @dat; for($i=0; $i<$n; $i++){ print MYHANDLE $dat[$i]; # ファイルに追加書き出し(ファイルがなければ新規作成される) print MYHANDLE ","; # カンマ区切りで書き出していく } print MYHANDLE "\n"; # 1行読み終えるごとに改行 } close MYFILE; # i番目のファイルを読み終えたら閉じる print $file, "\n"; # 読み込み・書き出しをしたファイル名を表示する } closedir DH; close MYHANDLE;

  • backs
  • お礼率85% (564/660)
  • Perl
  • 回答数2
  • ありがとう数2

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

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

(MS-DOS 風に書くと) c:\Perl\workdir にあるファイル名を使ってカレントディレクトリのファイルをオープンしようとしてるんだから, ディレクトリ c:\Perl\workdir が (このスクリプトを実行している) カレントディレクトリでなければ正しい動作をしないと判断できる. たとえば ・c:\Perl\workdir には test1.txt, test2.txt がある ・カレントディレクトリには test1.txt はあるが test2.txt はない というような状況であれば 「(カレントディレクトリにある) test1.txt は読み込めるが test2.txt は (カレントディレクトリにはないので) 読み込まない」 ということになる.

backs
質問者

お礼

回答ありがとうございす。 理解できました(^_^;) おっしゃるとおり、カレントディレクトリにtest1.txtだけが置いてありました。私はworkdirにあるtest1.txtが読み込まれたのだと思い込んでしまっていました。workdirにあるファイルを読み込みたければ、カレントディレクトリを先に変更しておかないといけなかったのですね。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

「対象となるディレクトリ」と「カレントディレクトリ」との関係は? 「ファイル名がきちんと取れていること」は確認できてますか? そして, 「必要なファイル」がオープンできていることも確かめていますか? そもそも何でこんなことを Perl でしている? それなりなコマンドたたくだけではダメなの? 動作には関係ないけど, なんで split してるんだろう. やってることって, 「行末にカンマを追加する」だけだよねぇ....

backs
質問者

お礼

すいません、聞かれていることに対してきちんと返答できているか分からないのですが。。。 > 「対象となるディレクトリ」と「カレントディレクトリ」との関係は? コメントに対象となるディレクトリと書いているのは、テキストファイルが保存されているディレクトリのことで、スクリプトを実行するたびに特定のディレクトリ(フォルダ)を指定したいためです。 > 「ファイル名がきちんと取れていること」は確認できてますか? ファイルに書き出しではなく、コンソール画面(コマンドプロンプト)に$fileに入れられた各ファイル名を評させると、きちんと表示されるのでファイル名を取得できていることは間違いなさそうです。 > 「必要なファイル」がオープンできていることも確かめていますか? 少なくともC:/Perl/workdirに保存されている2つのファイルのうち1つはきちんと読み込んで、ファイルへ書き出しもできています。 > そもそも何でこんなことを Perl でしている? これはスクリプトの一部なので、実際にはカンマ区切りのデータを読み込んで、途中で色々とやることがあるからです。

関連するQ&A

  • ファイルの入出力2

    指定したフォルダ内にあるcsvファイルのデータを 指定したhtmlファイルに出力するプログラムを書いているのですが、 下記のままだとcsvファイルにあるすべてのデータをとってきてしまいます。実現させたいことは「指定したフォルダ内にあるcsvファイル2行目のデータだけファイル出力する」というものです。 どなたかご協力お願いします。 #!/usr/bin/perl #--------------------------------------------------------------# # ディレクトリを開く #--------------------------------------------------------------# opendir(DIR,"test/"); #--------------------------------------------------------------# # 出力ファイル名を指定 #--------------------------------------------------------------# $dest = "test.html"; open (OUT, ">$dest") or die "$!"; #--------------------------------------------------------------# # 出力ファイルにhtmlを出力 #--------------------------------------------------------------# print OUT '<html> <head> <title>無題ドキュメント</title> <style type="text/css"> <!--.style1 {color: #FFFFFF}--> </style> </head> <body> <table width="419" height="105" border="0" cellpadding="0" cellspacing="0"> <tr> <th bgcolor="#000000"><span class="style1">名前</span></th> <th bgcolor="#000000"><span class="style1">住所</span></th> <th bgcolor="#000000"><span class="style1">性別</span></th> </tr>'; #--------------------------------------------------------------# # ディレクトリにあるファイル名を取得 #--------------------------------------------------------------# while ($filename = readdir(DIR)) { # ディレクトリにあるファイルパスを取得 $path = "test/$filename"; if(-f $path) { # ファイルオープン open (IN, $path) or die "$!"; while (<IN>) { # カンマ区切りでデータを取得&改行削除 chomp(@data = split(/,/, $_)); print OUT "<tr>\n"; # 各行の3つのカンマ区切りデータを取得 print OUT "<th bgcolor=\"#666666\">",$data[0],"</th>\n<td>",$data[1],"</td>\n<td>",$data[2],"</td>\n"; print OUT "</tr>\n"; } close(IN); } } #--------------------------------------------------------------# # ディレクトリを閉じる #--------------------------------------------------------------# closedir(DIR); print OUT "</table> </body> </html>"; #--------------------------------------------------------------# # ファイルを閉じる #--------------------------------------------------------------# close(OUT);

    • ベストアンサー
    • Perl
  • chdirがうまくできない

    はじめまして。hiro0777と申します。 perl初心者です。 お恥ずかしい内容なのですが、アドバイスいただければと思います。 環境はWindowsXP&Cygwinです。 質問内容:chdirがうまくできない。(ディレクトリ移動がうまくいかない) ・カレントディレクトリには、いくつかのサブディレクトリがあり、  サブディレクトリ名のみが書かれたファイル(dir.txt)がある。  dir.txtには「480iacrlc2」「480iacscan」といったディレクトリ名が1行ずつ記載。 ・dir.txtから1つずつサブディレクトリ名を読み取り、  そのディレクトリに移動し、ファイル処理をする。 #ここでコマンド引数にdir.txtを指定。 open(DIR, $ARGV[0]) || die "can't open $ARGV[0]\n"; while(1){ chomp($dir = <DIR>); #print "$dir\n"; chdir("$dir") or die "Cannot change directory '$dir'\n"; #system("pwd");  ###以降ファイル処理。 } 上記のようにやったのですが、うまくディレクトリを移動してくれません。 ちなみに以下のように直接ディレクトリ名を指定した場合はうまくいきました。 open(DIR, $ARGV[0]) || die "can't open $ARGV[0]\n"; while(1){ $dir = "480iacrlc2";#ファイル名を直接指定したら移動した。 chdir("$dir") or die "Cannot change directory '$dir'\n"; #system("pwd");  ###以降ファイル処理。 } テキストの扱いかたがいけないのかなぁと想像しているのですが。 どなたかご教授いただければ幸いです。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • ディレクトリ内のテキストファイルに対する同一処理

    よろしくお願いします。現在Linuxの環境でテキスト処理をしております。 ディレクトリ内にファイル名の異なった以下のような大量ファイルがあります。 a.txt 0,1,2,3,4,5,6,7 1,2,3,4,5,6,7,8 b.txt 2,3,4,5,6,7,8,9 3,4,5,6,7,8,9,10 これらのファイルをカンマでsplitし、左から2番目の数にだけ1を引き,下のディレクトリであるoutに出力させます。出力は以下のようになります。 ./out/a.txt 0,0,2,3,4,5,6,7 1,2,3,4,5,6,7,8 ./out/b.txt 2,2,4,5,6,7,8,9 3,4,5,6,7,8,9,10 そこで以下のようなPerlのプログラムを作成しました。 use strict; use warnings; my $dirname = '.'; opendir(DIR, $dirname) or die "$dirname: $!"; while (my $dir = readdir(DIR)) { next unless (-f $dir); next unless ($dir =~ /\.txt$/); print $dir, "\n"; open(FILE, $dir) or die "$dir: $!"; my @file = <FILE>; foreach $line (@file) { my ($a,$b,$c,$d,$e,$f,$g,$h) = split(/,/, $line);      my $b = $b - 1; close(FILE); } open(NEWFILE, "> ./out/$dir") or die "$dir: $!"; print NEWFILE @file; close(NEWFILE); } closedir(DIR); ですが、出力は完了するのですが、元のファイルから計算がされていません。どこがどう間違えているのかご指摘よろしくお願い申し上げます。

    • ベストアンサー
    • Perl
  • textareaに入力されたデータを読み込む

    例えば以下のようにtextarea内にデータが入力されているとします(カンマ区切り,スペース区切り,タブ区切りなどはなんでも良いのですが)。 +---ここから---+ 1 2 3 4 5 6 7 8 9 10 11 12 +---ここまで---+ これらのデータを配列に格納する方法が,だいぶネットサーフィンしていたのですが分かりません。 以降,Perlになってしまうのですが,1行ずつ配列にdat=(1,2,3,4)のように格納していくか,あるいは行列(2次配列)の形で格納したいのです。 $pathname="D://datafile.dat"; open MYFILE, "$pathname"; while (<MYFILE>) { chomp; @{"dat$."} = split /,/; } close MYFILE; +----------- $pathname="D://datafile.dat"; open MYFILE, "$pathname"; @dat = map {chomp;[split /,/]} <MYFILE>; close MYFILE;

  • 読み込んだデータを配列へ代入する方法

    ---ここから--- 1,2 3,4 ---ここまで--- このようなファイルを読み込んでデータを配列へ格納するには, $pathname="D://data.txt"; open MYFILE, "$pathname"; @list=<MYFILE>; for($i=0;$i<2;$i++){ @dat=split(/,/,$list[$i]); print @dat; } close MYFILE; といったようなforあるいはwhileで1つの配列(上の場合だと@dat)に1行のデータを繰り返し入れていく方法しか思い浮かびません。できれば1行目のデータは@dat1という配列へ,2行目のデータは@dat2という配列へ,といったように行ごとに別々の配列へ代入させたいのですが良い方法はないでしょうか。 もしくは@dat=([1,2],[3,4])のような2次配列の形にでもできれば最高なのですが、、、

    • ベストアンサー
    • Perl
  • ファイルの書き込み2

    またまた失礼します。 やりたいことは以下です。 1.ディレクトリを開く。 2.ファイル達を読み込み。 3.追記用のデータファイルを開く。 4.「2」にデータを追記 5.別のディレクトリに書き出し。 以上です。 4番がうまくいきません。 ためしに4の工程を抜かすと問題なく書き出されます。 4の工程でやりたいことは、 1.タブ区切りのテキストファイルを読み込み。 2.書き出し用に読み込んだ(追記したいファイル)<productのpath="[ココの値!]"を取得。 3.「2」番で取得した値と「1」番で取得した値を比較。 4.「3」がtrueの行を追記して書き出し。 以上。 要するになにがしたいかというと、 仮にタブ区切りテキストには10行分のデータがあるとします。 それぞれの行には3つ分の値が入っており、先頭にIDが付いています。 一番最初に読み込んだファイル(追記したいファイル)にも同様にIDが振られており(<product path="ココ")そのIDとタブ区切りテキストのIDが一致した行だけ追記したいということです。 下記のコードだとなぜか、 10行分のデータがすべて追記されてしまいます。 コードは以下です。 #!/usr/bin/perl #既存ファイル読み込み&追記 $n_dir = "newXml/"; $b_dir = "xml/"; opendir(DIR, $b_dir); while($file = readdir(DIR)){ $bfile="$b_dir$file"; $nfile="$n_dir$file"; $dfile="data/data.txt"; if (-T $bfile) { open(IN, $bfile);#既存ファイルオープン @list = <IN>; close(IN); open(OUT,">$nfile");#書き出しファイルオープン foreach $line (@list) { if ($line =~ /\<product/){ $line =~ /path=\".*\"/;#path取得 $1; } if ($line =~ /\<\/product\>/) { open(IN, $dfile);#追加データファイルオープン while($data = <IN>){ chomp(@data = split(/\t/,$data)); $data[0] =~ s/\//_/g; if($data[0] == $1){#取得したパスとdata.txtとってきた値を比較 print OUT <<EOF; <ds path="$data[0]">$data[1]</ds> <kw>$data[2]</kw> $line EOF } else{next;} } close(IN) }else{print OUT $line;} } close(OUT); } else{next;} } closedir(DIR); 長々と申し訳ありません。 エラーなどは特にありません。 ご協力お願いします。

    • ベストアンサー
    • Perl
  • readdir におけるフルパスでのファイル名取得(1)

    前提: current directory---perl scriptが存在する data directory -----.\DATA¥ current directory直下のフォルダ"DATA"に含まれるファイル名(text file)の取得は、 ------------------------------ opendir(DIR,"./DATA/"); @file=readdir(DIR); closedir(DIR); foreach $myfilename(@file){ if($myfilename=~/txt|TXT/){ print "$myfilename\n"; #確認用 } } で、できますが、フルパス付は、どのようにすればできるでしょうか? 現状、DOS promptで下記のようにやっています。 dir /s/b/o .\DATA\*.txt > filelist.dat これを、perlで読み込んで、処理をやっています。 readdirをうまく使って、perlの中で済ませてしまいたいのです。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • perl ディレクトリ ツリー表示

    下記ソースコードでカレントディレクトリのツリー表示ができますが、これを特定のディレクトリ内をツリー表示できるようにする方法がわかりません。 opendir関数の$dirの前にtestをつけましたが、うまく行きません。 特定のディレクトリは任意で変えることができることとします。 sub treelist_ { my ($dir, $lv) = @_; opendir my $dh, $dir; my @files = grep { $_ !~ /^\.\.?$/; } readdir $dh; closedir $dh; for my $file (@files) { print ">" x $lv, "$dir/$file\n"; treelist_("$dir/$file", $lv+1) if -d "$dir/$file"; } } sub tree { for my $dir (@_) { print "$dir\n"; treelist_($dir, 0); } } tree('.');

  • EXCELにテキストファイルを読込むマクロ作成

    EXCELにテキストファイルを「カンマ区切り」で読み込みしたいのですが、 下記マクロの内容ではカンマ区切りで正しくインポートされないのですが 作成方法ご伝授お願いいたします。 sub macro1()  dim myFile as string  myfile = application.getopenfilename(filefilter:="テキストファイル(*.txt),*.txt")  if myfile = "False" then exit sub  workbooks.opentext _   filename:=myfile, _   datatype:=xldelimited, _   textqualifier:=xltextqualifierdoublequote, _   tab:=true, _   comma:=true, _   space:=true ’予備  activeworkbook.worksheets(1).move before:=thisworkbook.worksheets(1) end sub

  • ファイルの書き込み

    以下のことがしたいです。 testフォルダよりテキストファイル達を読み込み、 ある行だけ取り除いたのちnewtestフォルダに書き出したいと思います。 以下、コードになります。 #!/usr/bin/perl $n_dir = "newtest/"; $b_dir = "test/"; opendir(DIR, $b_dir); while($file = readdir(DIR)){ $nfile="$n_dir$file"; $bfile="$b_dir$file"; if (-T $bfile) { open(IN, $bfile); #testフォルダよりファイルの読み込み @list = <IN>; close(IN); open(OUT,">$nfile"); #newtestフォルダに書き出し while(@list = <IN>) { #testフォルダ内のファイルを一行ずつ読み込み if (@list =~ /test/) { #行にtestという文字列があるぎょうだけ書き出し print OUT @list; } } close(OUT); } else{next;} } closedir(DIR); ということをやりたいのですが、 書き出されるファイルは空です。 どこが間違っているのでしょうか。 エラーなどは特にありません。 testフォルダのファイル達が そのままnewtestフォルダに書き出されるのですが、 中身は空です。 ご協力お願いします。

    • ベストアンサー
    • Perl

専門家に質問してみよう