• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:perl 複数ファイルから一行ずつ読み込んで比較)

Perl複数ファイルから一行ずつ読み込んで比較

TYWalkerの回答

  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.1

全部読むのは大変なので読みませんでした。すみません。 open FILE, $file; while (<FILE>) {   $_の処理 } close FILE; という処理の意味は分かりますね。 これと、 open FILE, $file; @arr = <FILE>; close <FILE>; for (@arr) {   $_の処理 } という処理はまったく同じです。 下では@arrという配列にファイルの中身をドバーンと入れて処理しています。 これだと、 open FILE, $file_1; @arr1 = <FILE>; close <FILE>; open FILE, $file_2; @arr2 = <FILE>; close <FILE>; という風に複数のファイルを処理するのも簡単ですし、 for $i (0 .. $#arr) { # 0 から $#arr まで番号を$iに入れて処理する。$#arrは配列の最後の指標。   next if $i % 2 == 1; # $i を2で割った余りが1だったらループを飛ばす   $arr[$i] の処理 } と言う風にやれば奇数の行の処理も出来るでしょう。 大きな問題を小さな問題に分解する考え方はいいんですが、だったらその小さな問題のうち、うまくいかない部分だけを質問してください。 じゃないと質問に答える人はウンザリしてしまいます。 それから、エラーが出たというだけではなくて、実際にどんなプログラムを動かしたら、なんというエラーが出たかも教えてください。

kazumaxneo
質問者

お礼

貴重な時間を割いて早速お答ええいただき、ありがとうございます。たいへん迅速にお答えいただいたので驚いています。 配列に読み込むという方法、やってみます。まずは、100行程度だけ抽出したテストファイルを用いて試して見ます。 ただこの方法だと、考え方が間違っているかもしれませんが、行が1000万以上ある場合、一度メモリにすべてキャッシュされ、計算機に負担が大きいのではないかと懸念しています。ただ、配列に読み込む方法は、ぼんやりとはしってましたが、書くこともテストしたこともないので、大変勉強になりました。重ね重ねありがとうございます。今から試してみます。 >大きな問題を小さな問題に分解する考え方はいいんですが、だったらその小さな問題のうち、うまくいかない部分だけを質問してください。じゃないと質問に答える人はウンザリしてしまいます。 自分も投稿後に感じました。申しわけないと思っています。 >それから、エラーが出たというだけではなくて、実際にどんなプログラムを動かしたら、なんというエラーが出たかも教えてください。 質問欄にスクリプトを記載するには、文字制限でできませんでした。不親切すぎて回答に困りますよね。すいませんでした。 以下が、書いてみたスクリプト原文です。ここまででは、エラーは出てきませんでした。 #!/usr/bin/perl use strict; use warnings; #まずは、後半に情報があるtextファイルだけ抜き出す文を書く #入力、出力のファイルハンドルを指定 open (IN1, 'file1') or die "$!"; open (IN2, 'file2') or die "$!"; open (OUT1, '>temp1') or die "$!"; open (OUT2, '>temp2') or die "$!"; #if内で定数を定義したらエラーになるので、ここで定義。 my $flg1 = 0; my $flg2 = 0; #まずはfile1から while (my $data1 = <IN1>){ #()があれば、$flg1に2を代入  if (data1 =~ /\(.*\)/){  $flg1 = 2;  } #$flgが0以上なら出力し、flgの値を1減らす。真なら2行続けて出力される。  if ($flg1 > 0){  print OUT1 $data1;  $flg1 = $flg1 -1; } } #file2も同様に処理する while (my $data2 = <IN1>){ #()があれば、$flg2に2を代入  if (data2 =~ /\(.*\)/){  $flg2 = 2;  } #$flgが0以上なら出力し、flgの値を1減らす。真なら2行続けて出力される。  if ($flg2 > 0){  print OUT2 $data2;  $flg2 = $flg2 -1; } } close IN1; close IN2; close OUT1; close OUT2; #各行の()で囲まれた部分の最初の2桁の数字だけ抜き出す #入力、出力のファイルハンドルを指定 open (IN3, 'temp1') or die "$!"; open (IN4, 'temp2') or die "$!"; open (OUT3, '>temp3') or die "$!"; open (OUT4, '>temp4') or die "$!"; while (my $data3 = <IN3>){ #(数字2桁 )があれば真、数字2桁を変数に代入。 if ($seq3 =~ /(\()([1-9][1-9])/{ my $none1 = $1; my $compare1 = $2; #改行を挿入 my $compare2 = "$compare1\n"; print OUT3 $compare2; } while (my $data4 = <IN4>){ #(数字2桁 )があれば真、数字2桁を変数に代入。 if ($data4 =~ /(\()([1-9][1-9])/{ my $none2 = $1; my $compare3 = $2; #改行を挿入 my $compare4 = "$compare3\n"; print OUT4 $compare4; } close IN3; close IN4; close OUT3; close OUT4; #次に、各行の数値の大小を比較する。この先、2ファイルの同じ行を #比較する方法が分かりませんでした。 exit

kazumaxneo
質問者

補足

補足というか、文字制限で書けませんので追記しています。私の書いた、上のつたないスクリプトでも、 抽出の対象となる、下のような構造の二つのファイルから、 file1 >text1. 4552221.2:(30.2):100 13333331 >text2 87999999 >text3. 3444444.1:(20.0):300 75533333 ・ ・ ・ ・ file2 >text1. 4552221.2:(20.9):100 13333331 >text2 87999999 >text3. 3444444.1:(23.3):300 75533333 ・ ・ ・ ・ から、()内の左端の2桁の数値だけ抽出して、下のように、一行ずつ出力することまでは とりあえず、エラーなくできています。 file1(temp3として出力) 30 20 ・ ・ file2(temp4として出力) 20 23 ・ ・ 1000万以上の行のテキストの場合、どの程度の実用性があるのか不明ではありますし、もっとコンパクトに出来るとは思うのですが。 一番お聞きしたいのは、この2つのファイルの各行の数値を順に比較して、数値に一定以上の差がある場合、その数値を出力する、というのをどのような表現やコマンドを用いればできるのか?、です。 しつこくて大変恐縮なのですが、どなたかぜひ教えて下さい。お願いします。whileでのループや、forでの全配列でのループ処理では、file1かfile2のどちらか一方を順に処理することはできますが、どちらのファイルも、一行ずつ交互に読み込んで処理するにはどうすれば良いのでしょうか?このような考え方自体、根本的に間違っていたら申しわけありません。

関連するQ&A

  • 二つのファイルから一行ずつ取り出して計算

    aaa.txt と bbb.txtというファイルがあり、それぞれ 1.1 0.1 -0.2 0.9 … といった感じで一行ずつ数値が入っています。 シェルスクリプトを用いて、 この二つのファイルから一行ずつ取り出して足し算を行いたい (例えばaaa.txtの一行目が1.1、bbb.txtの一行目が0.9なら1.1+0.9=2.0) のですが、どうすれば良いでしょうか。

  • 二つのファイルから一行ずつ取り出して計算

    aaa.txt と bbb.txtというファイルがあり、それぞれ 1.1 0.1 -0.2 0.9 … といった感じで一行ずつ数値が入っています。 C言語を用いて、上記ファイルを読み込み、 この二つのファイルから一行ずつ取り出して足し算を行いたい (例えばaaa.txtの一行目が1.1、bbb.txtの一行目が0.9なら1.1+0.9=2.0) のですが、どうすれば良いでしょうか。

  • perlをコマンドラインで実行したい

    今はperlをコマンドプロンプト上でファイルをコンパイルして実行結果を別のテキストファイルに出力しています。(printなど) ただ、こまごまとした置換え・変換などいちいちテキストファイルにperlを書いてコンパイルして出力ファイルを開いて取り出すというやり方にわずらわしさを感じてきました。 簡単なスクリプトであれば、使い捨ての方がよく感じており、 コマンドプロンプトで試してみたのですが、長い文章やソースなどを変数にいれることができず、(改行がEnterにとられてしまう??)また、一行にずらずらとかかなくてはならないので、うまくいきません。 なにか、テキストエディタのような感じで、このようなperlスクリプトをコンパイルできるようなものはあるのでしょうか。 copalというものを使ってみたのですが、 ファイルハンドルなどが使えなかったのでだめでした。 どなたかご協力お願いします。

    • ベストアンサー
    • Perl
  • テキスト比較コマンドのdiffについて

    unixコマンドにdiffというのがありますね。2つのテキストファイルを比較してその違いを出力するというものです。このコマンドの意味がわからないところがあります。 テキストAとBの比較とは、 1 両者が全く同じかどうかを比較するということなのか、 2 テキストAとBに含まれている各行を取り出してどこかに一致する行があるかどうかをチェックするということなのか 3 あるいはそれ以外の意味 どのようなことを意味するのでしょうか。 1だったら、1行付け加わっただけでそれ以降が同じものであったとしても全部検索対象となり出力されます。 2だったら、何をしたことになるのでしょうか。全く同じ内容で行構成を入れ替えたら検索に引っかからないことになります。 私の希望としては1なのですが、そうするとわけがわかなないぐらい多くの出力結果となることが多いはずです。オプションなどで対応するとは思いますが、基本的には何をするコマンドなのでしょうか。 よろしくお願いします。

  • 【FLASH】テキストファイルを一行ずつ表示させたい

    まだまだFLASH初心者のものです。 不可能な質問かもしれませんが、もしご存知の方がいらっしゃいましたら教えてください。 まず、私が実行したいことをいかに記載いたします。 ------------------------------------ 入力フォームより50文字程度のお知らせを投稿 ↓ ログファイル(log.txt)に一行ずつ投稿されたデータが記録される(最大10記録されます。) ↓ ログファイルのデータを一行ずつフラッシュで表示 (横に流れるニュースのようなかんじで) ------------------------------------ ログファイルの各行の最初に news1=書き込んだデータ1 &news2=書き込んだデータ2 というように変数を入れてあげれば、フラッシュで同じ変数を設定したテキストフィールドに反映させることはできるのですが、フォームから投稿したデータの場合、 書き込んだデータ1 書き込んだデータ2 と変数を頭につけることができません。 (フォームのスクリプト(php)で変数をつけて出力する方法も考えてみましたが常に最新の記事をnews1、ひとつ前の記事をnews2に変更して出力する方法がわからなかったので・・) もし、変数なしで一行ずつを表示させる方法をご存知の方がいらっしゃいましたら教えていただけますでしょうか。 また、ほかに良い方法がございましたらそちらも教えて頂ければと思います。

    • ベストアンサー
    • Flash
  • ファイルの処理について

    数百行のテキストファイルを5行づつ取り込んで処理をしたいのですが。。 どうすればいいのでしょうか? 一行づつは可能なんですが。。。 While(<FILEHANDL>){ 処理 } ヘルプ~。。。。

    • ベストアンサー
    • Perl
  • ファイルを行ごとに比較するシェルスクリプトについて

    ファイルを行ごとに比較するシェルスクリプトをご教授ください。 例えば(master.txt)(a.txt)(b.txt)(c.txt)(ok.txt)(ng.txt)と4つのファイルがあり、 (master.txt)と(a.txt)の行を比較し(a.txt)の中のある行が(master.txt)の行と一致した場合(ok.txt)に (master.txt)の行と一致しなかった場合(ng.txt)に入れる。 その後(master.txt)と(b.txt)の比較し(a.txt)が使用したものと同じ(ok.txt)or(ng.txt)に入れる・・・ といったように繰り返していくシェルスクリプトはどのようにして作成するのでしょうか? txtファイルの中の行はランダムに入っており、x.txtの一行一行ををmaster.txtの全行と比較する必要があります。 自分で作ってみたものは、while文を2重で使い一行ずつ取り出しcase文で行が一致した物を(ok.txt)に入れる 所までは成功しているのですが、複数回繰り返す時にどのようなロジックで不一致行を(ng.txt)に入れる ことができるのかが考え付きませんでした。 よろしくお願いいたします。

  • C++で、テキストファイルを一行ずつ読み込んで配列に入れたいのですが、

    C++で、テキストファイルを一行ずつ読み込んで配列に入れたいのですが、うまくできません! テキストには -3.0        1.0        2.0 ・・・などのように一行に一つの数値が入って縦に並んでいます。 それをひとつずつ読み込み、新しい配列(たとえばa[])に順番にいれたいのです。 a[1]=-3.0,a[2]=1.0、・・・と なるように。 どうか、この初心者にご指導お願いいたします。

  • バッチでテキストを出力したときに改行ができない

    バッチファイルでテキストを出力するのですが、改行ができません echo 一行目 > C:\temp.txt ? echo 二行目 >> C:\temp.txt として結果C:\temp.txtファイル内に  一行目  二行目 ではなく  一行目  二行目 としたいのですが、、 ?にはいるものがわかりません。 echo " " >> C:\temp.txt としても""が入ってしまうし echo   >> C:\temp.txt (全角スペース)を入れても"ECHO は <ON> です。"とメッセージが出てしまいます。 わかる方お願い致します。

  • ファイルのパターンマッチ処理の書き方

    現在Perlを勉強中です。 あるところからhtmlファイルをダウンロードした後、リンクを抽出する というスクリプトを、以下のように書いてみました。 (ファイルの各行について、「href="」と「"」の間にある、「"」以外が連続する部分を抽出する。 という考えです。) ----ここから------------------------------------------------- #!/usr/bin/perl ##################################################### #ここに、あるところから temp.htm をとってくる処理がある。# ##################################################### # temp.htm 中、 href でリンクされているページを出力 open ( FILE, "temp.htm"); while (<FILE>){ print ("$1\n") if /.*href="([^"]*.html)".*/; } ---ここまで-------------------------------------------------- この抽出部分はもっと簡潔に書けるものでしょうか? と言いますのは、これでも、Cに比べれば簡単なのですが、sedなら、 sed -n 's/.*href="\([^"]*.html\)".*/\1/p' temp.htm の1行で済むところなので、 一々ファイルを開いてwhileでまわすという書き方をするのが面倒だな と思いましたので質問させて頂きました。 (もっとも、sedはそのために特化したコマンドなので さすがにそれと同等に簡単に書けることを望むのが間違いなのかもしれませんが、 「簡単なことは簡単に...」がモットーのようなので、ひょっとしてという期待がありまして。。。) これは、私の書き方が冗長なのか、それとも、perlではこう書くのが普通なのか、 perlの勉強を始めたばかりで判断がつきません。 どちらなのかご教授いただけると幸です。 また、他にもこう書けるまたは私ならこう書くという御意見もお伺いできたら嬉しいです。 宜しくお願いします。

    • ベストアンサー
    • Perl