• 締切済み

Perlによるディレクトリ内の連続的な大量データ処理

Perlのテキスト処理に関する質問です.やりたいことはあるディレクトリ内に10000個ほどの(1)のようなテキストデータがあります.ここで私は(2)のプログラムを作成しました.しかしながら,このプログラムだと10000個あるテキストデータの一つしか処理できません.この処理内容をディレクトリ全体に適用させる方法はありますでしょうか?File::Find::Ruleなどがネット上にあったので使おうと努力しましたができませんでした.どなたかよろしくお願いします. (1)  2020 01 01 00 109.18970 18.36816 -2.317 -2.459 292.712 0.013 91.276 30.618 292.712 0.013 -2.317 -2.459 998.793 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 2020 01 01 00 109.54297 18.39178 -2.702 -2.652 292.653 0.013 90.044 30.676  292.653 0.013 -2.702 -2.652 993.902 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ・ ・ ・ ・ (2) use warnings; open INFILE, '<', '2020-01-01_00.txt' or die "file open error: $!"; while( <INFILE> ){ chomp if( /\n$/ ); $Year = substr($_,0,4); chomp if( /\n$/ ); $Month = substr($_,5,2); chomp if( /\n$/ ); $Day = substr($_,8,2); chomp if( /\n$/ ); $Time = substr($_,11,2); chomp if( /\n$/ ); $Lon = substr($_,16,9); chomp if( /\n$/ ); $Lat = substr($_,29,8); chomp if( /\n$/ ); $Temp = substr($_,57,7); chomp if( /\n$/ ); $Hum = substr($_,76,6); chomp if( /\n$/ ); $Ozone = substr($_,85,6); chomp if( /\n$/ ); $Rad = substr($_,140,5); $data = $Year. "-".$Month."-".$Day." ".$Time." ".$Lon." ".$Lat." ".$Ozone." ".$Rad." ".$Hum." ".$Temp."\n"; open($data, ">", "data.txt") or die("error :$!"); } # ファイルを閉じる close INFILE; exit;  

  • oswll
  • お礼率57% (39/68)
  • Perl
  • 回答数5
  • ありがとう数3

みんなの回答

  • okmotokun
  • ベストアンサー率59% (92/155)
回答No.5

> このプログラムだと10000個あるテキストデータの一つしか処理できません. 確認です。 MAC(またはMACで作ったテキストファイル)でやってるんですか。 1個のファイルは意図したように処理できて、そのように10000個のファイルを連続処理したい。ということですか。

oswll
質問者

お礼

なんとか自己解決できました.ソースは以下です. #!/bin/sh for i in ????-??-??_??.txt do cat $i | awk '{print $1"-"$2"-"$3,$4,$5,$6,$12,$18,$11,$13}' >> ./out/$i done 皆様,コメントありがとうございました.結局Perlではなくshでできました.

oswll
質問者

補足

okmotokun様 コメントありがとうございます. もう何日も挑戦していますが,一向に進みません.環境はWindows XP でActivePerlを用いています. なんとかほかの方法でできないかとVMwareでUbuntuをエミュレートし試行錯誤していますが,shとawkで以下のようなスクリプトを作ってみました. #!/bin/sh for i in ????-??-??_??.txt do cat $i | awk '{print $1"-"$2"-"$3,$4,$5,$6,$12,$18,$11,$13}' done しかしながら,この方法だと処理内容を個別のファイルとして保存できません. Perlもしくはshでもよろしいので,解決方法をお教えいただけないでしょうか? 大変厚かましい要望ですが是非ともよろしくお願い申し上げます.

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

本筋とはまるで関係ないところだけど、substr 連発で切り出してるヤツ、 unpack一行で取ったほうがすっきりすると思います。 というかスペースでsplit 一発?

oswll
質問者

お礼

ありがとうございました。解決できました。

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

あ~, open の行は間違ってますね. すみません. 適当にコンマを入れてください. ただ, 「どうもうまくいきません」と言われても, 何がどう「うまくいかない」のかわからないんですけど. とりあえず $filename にファイル名が入っていることは確認できますか?

oswll
質問者

お礼

ありがとうございました。解決できました。

回答No.2

サブディレクトリを無視してよいのなら下記が簡単かと思います。 while(<*.txt>){ print "$_\n"; }

oswll
質問者

補足

shippo_ppk様 ご回答ありがとうございました。ぜひ明日やってみます。

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

単純に * を glob してファイル名のリストを作っちゃうとか, opendir+readdir+closedir とか. 前者でいけば for my $filename (glob '*') { open INFILE '<' $filename or die .... 処理 } と思う. ところで, chomp if /\n$/; って全く意味ないし, chomp を同じオペランドに対して複数回やっても無意味です. chomp の機能は理解できてますか?

oswll
質問者

補足

Tacosan様 ご回答ありがとうございました.3時間ほど粘ってみたのですが,どうもうまくいきません.教えて君になってしまい大変恐縮ですが,ぜんソースを教えていただけないでしょうか.よろしくお願いします.chompの内容はだいたい理解できました.

関連するQ&A

  • perlで、文字列の中から何番目から何番目までの文字を抜き出したい

    perl初心者です。 文字列の中から何番目から何番目までの文字を抜き出して 別のファイルにうつす、 というスクリプトを書いています。 でも、うまくうごいてくれません。。。 恐らく、根本的におかしな部分があると思いますし、 さらに、何番目から、は指定できていても、 次の数字は文字数を意味しているのだと思いますので、 意図するものと違う気がします。 ただ、何番目から何番目 という情報だけを入力してできたら作業上大変助かります。 本当に困っております。 アドバイスをいただけると幸いです。 大変急いでおります(;;)。 宜しくお願いします!!! #!/usr/bin/perl ; open(IN, "test.txt") or die ; open(OUT, ">after_test"); while(<IN>) { chomp ; if (/(\S+)/) { \S = $S substr ($S, 12345, 12389) = { print OUT "$_\n"; } } } close (IN) ; close (OUT) ;

    • ベストアンサー
    • Perl
  • Perlで2つのテキストファイルの処理する方法

    めぐみです。 tatsu99さま、以下のプログラムを親切にアドバイス頂きまして本当にありがとうございました。 追記で質問させて頂きたいことがあります。 --------------------------------------------------------------- $file_a = shift(@ARGV); $file_b = shift(@ARGV); open FHA,$file_a or die("can't open $file_a"); @data_a = (); while($line=<FHA>){ chomp($line); push @data_a,$line } close FHA; open FHB,$file_b or die("can't open $file_b"); @data_b = (); while($line=<FHB>){ chomp($line); push @data_b,$line } close FHB; foreach $da (@data_a){ printf("%s%d%d%d\n",$da,$data_b[0],$data_b[1],$data_b[2]); printf("%s%d\n",$da,$data_b[0]); printf("%s%d%d\n",$da,$data_b[1],$data_b[2]); printf("%s\n",$da); printf("%s%04d%02d%02d\n",$da,$data_b[0],$data_b[1],$data_b[2]); printf("%s%02d%02d\n", $da,$data_b[1],$data_b[2]); printf("%d%d%d%s\n",$data_b[0],$data_b[1],$data_b[2],$da); printf("%d%s\n",$data_b[0],$da); printf("%d%d%s\n",$data_b[1],$data_b[2],$da); printf("%s\n",$da); printf("%04d%02d%02d%s\n",$data_b[0],$data_b[1],$data_b[2],$da); printf("%02d%02d%s\n",$data_b[1],$data_b[2],$da); }--------------------------------------------------------- 下記のような内容を追加で出力させることは難しいでしょうか。 1.B.txtを元に下記のように数字だけのデータも追加で出力させたかったです(1行目1986,2行目3,3行目6の場合) 198636 1986 36 19860306 0306 2.A.txtを元にA.txtから下記の内容も追加で出力させたかったです(4行目以降は無視して構いません)。 1行目と2行目 2行目と3行目 3行目と1行目 2行目と1行目 1行目と3行目 3行目と2行目 以上、何卒よろしくお願いいたします。

  • Perlのプログラミングについて

    Perlのプログラミングでつまづきました。 # ファイルから指定文字列を含む行を収集する # 入力ファイルのオープンと読み込み print( "入力ファイル名?" ); $n = <STDIN>; chomp( $n ); open( FIN, "<$n" ) or die "入力ファイルオープンエラー: $!\n"; $n = @a = <FIN>; close( FIN ); print( "$n 行読み込みました\n" ); # 行の収集 print( "検索文字列?" ); $x = <STDIN>; chomp( $x ); $ptn = $x; #指定の文字列 $x = @b = grep( /$ptn/, @a ); print( "$x 行見つかりました\n" ); # 出力ファイルのオープンと書き出し print( "出力ファイル名?" ); $y = <STDIN>; chomp( $y ); open( FOUT, ">$y" ) or die "出力ファイルオープンエラー: $!\n"; print FOUT ( $ptn, "\n" ); print FOUT ( $x, "\n" ); print FOUT ( @b ); close( FOUT ); というプログラムで実行すると C:\My Perl\pl>perl プログラムの実行.pl 入力ファイル名?sample1.txt 168 行読み込みました 検索文字列?k 45 行見つかりました 出力ファイル名?out3-24.txt 続行するには何かキーを押してください . . . となり出力ファイルの中身が表示されません。 どこを間違えているのかご指摘いただけないでしょうか?

  • Perl。文字出現回数を重複しないでカウントしたい。

    perl初心者です。どうぞ助けて下さい。 以下のようにデータがならんでいる時、 pphhhppphhhppppppphhppppppppppppppppppphhh pが連続した文字の連続数は 2、3、7、19 となります。 今、知りたいのはこのようなpの連続数の出現回数です。つまり、たとえばpが19回連続してあるものは何回でてきたか、が知りたいのです。 上の例だと1回が正解となります。 ところが、スクリプトを書くとき、 たとえば以下のようにしたとき、 pが19回なら重複カウントはなくても、 pを2でカウントしたら、 本当に出てきて欲しいこたえは一回なのに、 P=3、7、19のどれにも該当してしまいます。 #!/usr/bin/perl ; open(IN, "text1.txt") or die ; open(OUT, ">text1out.txt"); while(<IN>) { chomp ; if (/(\S+)/) { $name = $1 ; if ($name =~ /^ppppppppppppppppppp/) { {$count++;} ; } print OUT "$count\n" ; } } close (IN) ; close (OUT) ; 正規表現の中を工夫すればいいのだと思いますが、 大変困っております。宜しくお願いします。

    • ベストアンサー
    • Perl
  • perl ファイルのデータを編集したい

    初めまして、perl をやり初めたばかりです。作業は Linux 上で行ってます。 あるテキストファイル data.txt があります。 data.txt の中は、以下のようになっているとします。 100 200 300 400 500 600 これを読み込んで、例えば、 1 2 3 4 5 6 以上の様に各数字を百分の一にして出力したいと思ってます。 一応、色々と調べながらプログラムを書いてはみましたが 思う様に出力されません。以下そのプログラム。 #!/usr/bin/perl open(IN, "data.txt") or die ; @x = <IN>; close (IN); $ref_x = \@x; $n_data = @x; for ($i = 0; $i< $n_data; ++$i) { $$ref_x[$i] /= 100 ; print $x[$i], " "; } print"\n"; どなたか、perl にお詳しい方教えていただけないでしょうか? 宜しくお願い申し上げます。

  • Perl 教えてください。

    下記のような簡単なスクリプトなんですが、なぜかサーバーにアップすると動きません。 ローカルでコマンドプロンプトから直接実行するとまともに動作します。 パーミッションは「755」と「705」でやってみましたが。 perlのパスは合っていますし、実際同じ場所に置いた他のCGIは動作します。 #!/usr/bin/perl open (DT, "<./data/***/***.csv") or die "File '***.csv' Open Error."; @data = <DT>; $data[0] = ",,,,,,\n"; open (OUT,">./data/***/***1.csv") or die "File '***1.csv' Open Error."; print OUT @data; close (DT); close (OUT); 原因が分からず困っています。 解決策でなく、原因と思えるだけの回答で結構ですので何卒よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • perl 計算結果をファイルへ出力したい

    perl やり始めたばかりです。宜しくお願いします。 入力ファイル data.txt があるとします。 data.txt は、 123 456 789 333 555 777 以上のようなテキストファイルといたします。このファイルを 以下の様に100分の1にして出力したい。 1.23 4.56 7.89 3.33 5.55 7.77 と言うことで、この場で教えていただきました。それが、以下です。 #!/usr/bin/perl open(IN, "data.txt") or die ; @x = <IN>; close (IN); foreach $line (@x){ chomp($line); @elms = split(' ',$line); foreach $data (@elms){ print $data/100," "; } print "\n"; } おかげ様でこれはこれで上手く動きました。そこで、出力値をファイルに 書き込みたいのです。 もちろん、以下の様な方法でファイルに 書き込めるのは判っております。 計算プログラム.pl > outfile.txt しかし、上のプログラムをベースにファイルに書き込めないかと色々と 試してはみましたが、どうも上手く行きません。 どなたか教えて頂けないでしょうか? 宜しくお願い申し上げます。

    • ベストアンサー
    • Perl
  • Perl 処理速度について

    ブログを作成し、カテゴリー別に分けたく下記のようなソースを 書きました。 sub category1 { open(FILE, "<$FILE") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; $a = 0; my @category1 = grep(/,1,/, @DATA); while (<@category1>) { $a++; } &buffer(); if($start > @DATA) {$start = @DATA;} $next = $start + 100; $back = $start - 100; if ($back < 0) { $back = 0; } for ($i=$start;$i<$next;$i++){ last if ($i > @category1); $data = $category1[$i]; &page(); } } これの処理速度が遅いのですが、なにか原因はありますでしょうか? 似たような処理で下記のソースの方が、読み込む内容としては多いのですが、 こちらは普通の速度です。 sub diary2017 { open(FILE, "<diary/diary-2017.txt") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; &buffer(); if($start > @DATA) {$start = @DATA;} $next = $start + 1000; $back = $start - 1000; if ($back < 0) { $back = 0; } for ($i=$start;$i<$next;$i++){ last if ($i > @DATA); $data = $DATA[$i]; &page(); } } カテゴリーのサブルーチンとアーカイブ専用のサブルーチンで違う点といえば $a = 0; my @category1 = grep(/,1,/, @DATA); while (<@category1>) { $a++; } このgrepのとこですが、 これが遅いとすると対処方法はありますか? ※開くファイルはアーカイブは直接名前にしてて、カテゴリーは変数を使ってますが  これは同じです。

    • ベストアンサー
    • Perl
  • 効率の良いデータ照合のさせ方

    2つのCSVファイル(どちらもデータ件数が1000件を超える)を照合して SQL文の発行の有無を処理するプログラムを組んでいます。↓ open(ファイル1, ファイル1の場所) || die("$!"); while(<ファイル1>){ chomp($_); @data_1 = split(/,/, $_); open(ファイル2, ファイル2の場所) || die("$!"); while(<ファイル2>){ chomp($_); @data_2 = split(/,/, $_);   # ここでファイル1の指定した列のデータとファイル2の指定した列のデータ照合しています。↓   # ($data_1[列]、$data_2[列]) if(($data_1[0] == $data_2[5]) and ($data_1[1] == $data_2[3]) and ($data_1[3] == $data_2[4]) and ($data_1[4] == $data_2[0])){ #insert文     #update文 } } } 上記のような組み方をすると、やはり実行速度がかなり遅くなりました。 8分ぐらい処理にかかってしまいました; 効率的な処理のさせ方ということで、関数などを調べているのですが、 これという関数も見つからず困っています。 プログラムの組み方自体に問題があるとは思うのですが・・ なにぶん、経験が浅いというのもあり・・・; 何か良い方法をご存知の方、ご指導お願いします。

    • ベストアンサー
    • Perl
  • ファイルの入出力と改行

    縦100文字横70文字のデータが入ったデータファイルを横50文字にして並べ直したいと思い、まず試しに標準出力でそれがうまくいくかやってみたのですが、うまくいきません。もしお分かりであれば教えていください。よろしくお願いいたします。 #! /usr/bin/perl $filename = "reference.txt"; open HANDLE, "<$filename" or die "cannot open :$!"; print "open success\n"; @array = <HANDLE>; $count = 1; foreach $var (@array) { chomp $var; # print $var; if($count==50){ print $var, "\n"; } else{ print $var; } $count++; } close HANDLE; print "\n";

    • ベストアンサー
    • Perl

専門家に質問してみよう