• ベストアンサー

テキストファイルの編集

以前にもperlでのプログラミングについて質問させて頂いた者です。 前回と被る所があるのですがちょっと複雑で、私の手に負えないので質問させて頂きます。 よろしくお願いします。 データファイルAからデータを取得して、テキストファイルBの内容の一部を取得したデータで書き換えるという操作を行うプログラムを作りたいです。 具体的には、 データファイルA[A.txt]の中身 100 111  200 222 300 333 400 444 テキストファイルB[B.txt] 1st step 文字列1 start="123" end="134" 2nd step 文字列2 start="234" end="245" 3rd step 文字列3 start="345" end="356" 4th step 文字列4 start="456" end="467" という二つのファイルを読み込み、B.txtの""で囲まれた部分を、A.txtで取得したデータで置き換えるような操作を行いたいのですが・・。 A.txtの一行目で取得したデータをB.txtの1stステップの始まりと終わりの値として置き換え、それを二行目は2ndと同様の操作を行うようなプログラムを作りたいです。 もともとこのような操作を行いたくて前回のような質問をし、それを参考にし今日まで考えましたがやはり難しく、また頼りたいと思います。。 どうかよろしくお願いします。

  • Perl
  • 回答数3
  • ありがとう数3

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

  • ベストアンサー
  • sample_
  • ベストアンサー率76% (20/26)
回答No.2

再び、お答えしますねん。 if($data_b[$i] =~ s/".+" end=".+"/"$start[$ii]" end="$end[$ii]"/){$ii++}; の正規表現は、B.txt内にダブルクォートで囲まれた部分が2箇所しかないことを前提に書いたもので "→ダブルクォートで始まり、 .→何か一文字が +→1個以上続き、 "→ダブルクォートで閉じ →半角スペースが続き end"→endとダブルクォートが続き .→何か一文字が +→1個以上続き、 "→ダブルクォートで閉じる文字列。 ということで、 文字列1 start="123" end="134" を例に考えると "123" end="134" にマッチするので 123→$start[$ii] 134→$end[$ii] で置き換えてます。 ただし、他にダブルクォートで挟まれた場所が増えるとNGになるわけで… <src="文字列1" start="123" end="134"/ 1列目> だと 最初のダブルクォートからあてはまってしまい 文字列1" start="123→$start[$ii] 134         →$end[$ii] で置き換えてしまいます。 なので、条件を下記に返るとOKですね。 if($data_b[$i] =~ s/"[^"]+" end="[^"]+"/"$start[$ii]" end="$end[$ii]"/){$ii++}; 今度は、ダブルクォート内にダブルクォート以外の一文字が1個以上続く場合に条件を変えました。 これで、今まで "文字列1" start="123" がstart部としてヒットしていたのが "123"(ダブルクォートを含まない文字列)になるので期待したとおりになりますよ。 他の書き方だと、置換したいところが数字しか来ないのであれば if($data_b[$i] =~ s/"\d+" end="\d+"/"$start[$ii]" end="$end[$ii]"/){$ii++}; こんなんでもOKですね。

watashino7
質問者

お礼

疑問に思っていた点が解決致しました。 丁寧な回答本当にありがとうございます。 前回の質問から今回最後まで付き合っていただいて本当に感謝します。

その他の回答 (2)

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

書いちゃったので参考までに。 use strict; use warnings; my $datafile = 'a.txt'; my $targetfile = 'b.txt'; open my $ifh, '<', $datafile or die "can't open $datafile ($!)"; my @data; while (my $line = <$ifh>) { chomp $line; push @data, [split q{ }, $line]; } close $ifh; open my $tfh, '<', $targetfile or die "can't open $targetfile ($!)"; my $tmpname = $targetfile . '.tmp'; open my $tmp, '>', $tmpname or die "can't open work file ($!)"; while (my $line = <$tfh>) { if (index($line, '"') >= 0) { my $datum_ref = shift @data; $line =~ s{(".+?)" (\s+ end=) "(.+?)"}{"$datum_ref->[0]"$2"$datum_ref->[1]"}x; } print {$tmp} $line; } close $tfh; close $tmp; rename $targetfile, $targetfile . '.bak'; rename $tmpname, $targetfile; 修正前のファイルも残したほうがいいよね、つーことで。 本当はもうちょっとこったやり方をしないといけないのだけど手抜き。 #.+ → .+? だけのつもりだったのに何をやってるんだ

watashino7
質問者

お礼

サンプルプログラムありがとうございます。 参考に致します。 丁寧な回答ありがとうございました。

  • sample_
  • ベストアンサー率76% (20/26)
回答No.1

前回のコードをちょいちょい改造して回答します。 -------------------------------------------- use strict; use warnings; open (my $fh1, "<", "A.txt") or die "$!"; chomp(my @data_a = <$fh1>); close $fh1; my (@start, @end); for(my $i=0; $i<@data_a; $i++){ ($start[$i], $end[$i]) = split(/ /, $data_a[$i]); } open (my $fh2, "+<", "B.txt") or die "$!"; my @data_b = <$fh2>; for(my $i=0, my $ii=0; $i<@data_b; $i++){ if($data_b[$i] =~ s/".+" end=".+"/"$start[$ii]" end="$end[$ii]"/){$ii++}; } seek $fh2, 0, 0; truncate $fh2, 0; print $fh2 @data_b; close $fh2; -------------------------------------------- ざっくりした流れは A.txtをopenして、データを読み込みます。 この時chompで改行コードを落とします。(残しておくとB.txtに書き込んだ際に改行されちゃうので) closeして A.txtの内容をstart用とend用にsplit関数で 半角をセパレータとして分割しておきます。 読書きモードでB.txtをopenして、データを読取(今回はchompしない) 後は、B.txtを格納した配列をfor文でぐるぐる回して 置換作業を行います。 A.txtとB.txtの行数が違うので$iと$iiの別々の変数を用意して 取り出し置換を行っています。 後は、seek関数でB.txt内のカーソル位置を先頭に戻し truncate関数で0バイト(消去)してあげ 改めて書き直せば完成! こんなんでいかが(^^;)

watashino7
質問者

補足

サンプルソースプログラム非常に参考になりました。 ありがとうございます。 if($data_b[$i] =~ s/".+" end=".+"/"$start[$ii]" end="$end[$ii]"/){$ii++}; の行についての追加での質問なのですが、これはend=を探し、その前後の""で囲まれた部分をA.txtのデータで置き換えるという動作を行っているのでしょうか? 私が具体例として上げたB.txtではこの動作でやりたいことが出来るのですが、end=の行に置き換えたいデータ部の他に""で囲まれた文字列があった場合、上手く行きませんでした。 start=後の""をA.txtのスタートデータで置き換え、 end=後の""をA.txtのエンドデータで置き換えるようなプログラムにすればこれは解決するのでしょうか? 具体的にやりたいことは、 <src="文字列1" start="123" end="134"/ 1列目> からプログラムを通して、 <src="文字列1" start="100" end="111"/ 1列目> というように置き換えを行いたいです。

関連するQ&A

  • ファイル操作について、テキストファイルの書き換え

    よろしくお願いします。 データファイルAからデータを取得して、テキストファイルBの内容の一部を取得したデータで書き換えるという操作を行うプログラムを作りたいです。 具体的には、 データファイルA[A.txt]の中身 111 222 333 444 テキストファイルB[B.txt] 文字列1="123" 文字列2="234" 文字列3="345" 文字列4="456" というような二つのファイルを読み込み、B.txtの""で囲まれた部分を、A.txtで取得したデータで置き換えるような操作を行いたいのですが・・。 使用する言語としてはスクリプト言語であるperl、もしくはプログラム作成経験があるCを使用しようと思っています。(perlは未経験で入門書を読んでいるレベル)

    • ベストアンサー
    • Perl
  • DOS 特定の文字列を含むファイルのみの抽出方法

    C直下に2つのテキストファイル「A.txt」「B.txt」が存在するとします。 Aには「Start」、Bには「Second」という文字列が含まれているとします。 これらのテキストを、BATを使って『テキスト内に特定の文字列が含まれているファイル』のみをDOSプロンプト上に表示する方法をご教示願います。 ■想定するコマンド実行結果 ・Start.BATを実行→DOSプロンプトにて「A.txt」のみが表示する。 ・Second.BATを実行→DOSプロンプトにて「B.txt」のみが表示する。 よろしくお願いします。

  • PHPで複数のテキストファイルを読み込みたい

    PHPを勉強中です。 どうしても自力で解決できないので助けてください。 やりたい事は、 「複数ファイルの内容を読み込み、  それらのデータをcsvのセルに入れたい。」のです。 Aというフォルダに、複数のテキストファイルがあります。 これら各ファイルの内容をそれぞれ取得して 「○○.csv」のB列に上から順々に書き込んでいきたいのです。 Aフォルダに入っているテキストファイルは連番を想定しています。 A/ 0001.txt 0002.txt 0003.txt : フォルダに入っているテキストファイルの数はいろいろです。 3枚のフォルダもあれば100枚のフォルダもあります。 これらのファイルの内容を、それぞれ取得して 用意されているcsvファイルの特定のセルに テキストファイルの数だけ順番に入れていきたいのです。 ○○.csv A列  |  B列  |  C列  | △  |0001.txt内容|  △  | △  |0002.txt内容|  △  | △  |0003.txt内容|  △  | : : プログラムのヒントを教えていただければ嬉しいです。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • Excelで複数のテキストファイルを1枚のシートに

    Excelで複数のテキストファイルを1枚のシートに追加したいのですが可能でしょうか? VBAや別ソフトを複数使ってもかまいません。 2列のテキストファイルが複数ありA列目は共通でB列目がそれぞれ異なります。 data01.txt、data02.txt…と50ぐらいのファイルがあり、それぞれ A  B 10 1.24 20 2.56 30 2.46 :  : となっています。これをひとまとめにして A      B     C ・・・ data01  data02   data03・・・ data50 10     1.24    1.35 ・・・ 2.24 20     2.56    2.22 ・・・ 1.34 30     2.46    3.23 ・・・ 5.45 :       :      : といった表にしたいのです。 お願いします。

  • perlでファイル内を検索

    perlでファイル内を検索して読み込みを行いたいのですが どのようにすればよいでしょうか。 環境は、Solaris10 以下のようなファイル(test.txt)から  #start1~#endの間にある、”01:”で始まっている値をすべて取得する。  複数行になっている場合、カンマで1つにする。  ”01”ではじまっていないものは無視する。#などで始まっているものも。 ●ファイル:test.txt #start1 01:abc,aaa,bbb 01:1234 #01;a1,b1,c1 02:(省略) 03:(省略) #end #start2 01:(省略) 02:(省略) 03:(省略) #end #start4 01:(省略) 02:(省略) 03:(省略) #end ●結果 abc,aaa,bbb,1234 として読み込みたい。

  • テキストファイルのデータの追加

    二つのテキストファイルを結合というより新規のデータだけを追加したいのですが、そのようなコマンドはあるのでしょうか? 今は copy a.txt+b.txt c.txt copy c.txt b.txt を動かした後、テキストbを開いてテキストaとテキストbの重複しているデータを手作業で消しています。 また、上の2行のコマンドを1行にすることは可能でしょうか?

  • テキストファイルの一部置換したファイルをたくさん作りたい

    テキストファイル(a.txt)があるのですが このファイルの一部の文字列aaaをbbbに置換したファイル(b.txt)を作りたいです。 また文字列aaaをcccに置換したファイル(c.txt)も作りたいです。 続けてd.txtやe.txt・・・と作っていきたいですが簡単にできるフリーソフトはないでしょうか? 現状はa.txtを開いてaaaをbbbに置換して、別名で保存するのを繰り返し(10回以上)するので大変です。 このようなことが楽にできるフリーソフトがあれば教えてください。

  • perlで指定範囲を複数ファイルに分割する方法は?

    お世話になります。 perlを使用して、 下記の元ファイル[infile.txt]よりstart~endの範囲を各テキストファイルに 分割出力する方法をご教授いただけないでしょうか。  ※出力ファイル名は元のファイル名 (infile) + 1行目の文字列(単語)にします。   例>>infile_1111.txt , infile_333.txt よろしくお願いいたします。 [infile.txt] aaaa bbbb start 1111 2222 end dddd eeee start 3333 4444 end

  • エクセルの各セルの内容をそれぞれ1つずつテキストファイルに出力する方法

    掲題の件についてご存知の方がいらっしゃいましたらご教示ください。 エクセルファイルの列Aの内容がタイトルで、列Bの内容が本文であるテキストファイルを作成したいと考えています。 例えば、エクセルファイルに以下のようなデータを保持しているとします。 列A  列B 001  あいうえお 002  かきくけこ 003  さしすせそ この場合、001.txtは本文が「あいうえお」、002.txtは本文が「かきくけこ」、003.txtは本文が「さしすせそ」というように、エクセル1行についてテキストファイルを1つ作成したいと考えています。 このような処理を短時間で実施するのに適した方法をご存知の方がいらっしゃいましたらご教示いただければと思います。 どうぞよろしくお願いいたします。

  • エクセルのセルをテキストファイル出力する方法教えてくれませんか。

    初心者ですが、 どなたか、エクセルのセル1つを、 テキストファイル出力できる方法をご存知ですか? 詳細には、 エクセルファイルの列Aの内容がテキストファイル名で、 列Bの内容が本文であるテキストファイル出力を 約3000個、順次したいと考えています。 例えば、エクセルファイルに以下のようなデータを保持しているとします。 列A  列B 001  あいうえお 002  かきくけこ 003  さしすせそ この場合、001.txtは本文が「あいうえお」、 002.txtは本文が「かきくけこ」、 003.txtは本文が「さしすせそ」というように、 エクセル1行についてテキストファイルを1つ作成したいと考えています。 このような処理を短時間で実施するのに適した方法をご存知の方がいらっしゃいましたらご教示いただければと思います。 どうぞよろしくお願いいたします。

専門家に質問してみよう