• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:複数のテキストから同じ行数の文字列を抽出し,別のテキストに出力する方法)

複数のテキストから同じ行数の文字列を抽出し、別のテキストに出力する方法

このQ&Aのポイント
  • 複数のテキストから同じ行数の文字列を抽出し、別のテキストに出力する方法について説明します。
  • 具体的な手順としては、まずはじめに、同じディレクトリ内にある数千個のテキストから同じ行数の文字列を抽出します。
  • その後、抽出した文字列を別のテキストファイルに出力します。最後に、作成したテキストファイルを指定したディレクトリに保存します。

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

  • ベストアンサー
  • iriyak
  • ベストアンサー率48% (40/82)
回答No.2

こんにちは。 2020-*.txt はカンマで区切られたレコード。3列目 ($3) と 4列目 ($4) の値の組み合わせが lonlat.txt の<$1, $2>となっているレコードを抽出して、out/$1,$2.txt に格納したい。 質問者のやりたいことが仮にそうだとしてちょっと頭の運動をやってみました。Awk を用いた方法です。ご参考まで。 (処理の概要) (1) lonlat.txt から、そのような Awk プログラム (target.awk) を生成する Awk プログラム (gen.awk) を用意する (2) awk -f gen.awk > target.awk (3) awk -f target.awk 2020-*.txt (ポイント) 一度に Bourne Shell で作りこむかわりに、そういう動きをする Awk プログラムを作ってそれを起動するという風に分割している所です。このように分割すると、色々と後で取り換え可能です。下記実行例ではインタラクティブに最終ファイルを作成しましたが、これを Shell でまとめるのはたやすいことでしょう。 target.awk に与える 2020-*.txt が日付順に並んでいることをあてにしたプログラミングですが、そうなっていなくとも、out/*.txt のレコードを整列するよう改善すればより頑健になりますね。 (コマンドラインのダンプ) zebra[Sun]$ ls 2020-01-01_00.txt gen.awk target.awk 2020-01-01_01.txt lonlat.txt 2020-01-01_02.txt out/ zebra[Sun]$ head 2020-*.txt ==> 2020-01-01_00.txt <== 2020-01-01,00,109.18970,18.36816,30.618,0.000,91.276,292.712 2020-01-01,00,109.54297,18.39178,30.676,0.000,90.044,292.653 2020-01-01,00,109.89642,18.41394,30.581,0.000,89.560,293.056 ==> 2020-01-01_01.txt <== 2020-01-01,01,109.18970,18.36816,27.998,350.080,85.071,294.773 2020-01-01,01,109.54297,18.39178,28.187,355.642,86.229,294.425 2020-01-01,01,109.89642,18.41394,28.136,359.157,87.494,294.675 ==> 2020-01-01_02.txt <== 2020-01-01,02,109.18970,18.36816,30.200,551.398,75.640,296.445 2020-01-01,02,109.54297,18.39178,30.356,556.004,79.117,295.921 2020-01-01,02,109.89642,18.41394,29.953,558.076,82.460,295.942 zebra[Sun]$ cat gen.awk BEGIN { FS = "," print "BEGIN { FS = \",\" }" } { key1 = $1 key2 = $2 s = "$3 == key1 && $4 == key2 { print >> \"out/key1,key2.txt\" }" gsub(/key1/, key1, s) gsub(/key2/, key2, s) print s } zebra[Sun]$ awk -f gen.awk lonlat.txt BEGIN { FS = "," } $3 == 109.18970 && $4 == 18.36816 { print >> "out/109.18970,18.36816.txt" } $3 == 109.54297 && $4 == 18.39178 { print >> "out/109.54297,18.39178.txt" } $3 == 109.89642 && $4 == 18.41394 { print >> "out/109.89642,18.41394.txt" } zebra[Sun]$ awk -f gen.awk lonlat.txt > target.awk zebra[Sun]$ awk -f target.awk 2020-*.txt zebra[Sun]$ ls out/*.txt out/109.18970,18.36816.txt out/109.89642,18.41394.txt out/109.54297,18.39178.txt zebra[Sun]$ head out/*.txt ==> out/109.18970,18.36816.txt <== 2020-01-01,00,109.18970,18.36816,30.618,0.000,91.276,292.712 2020-01-01,01,109.18970,18.36816,27.998,350.080,85.071,294.773 2020-01-01,02,109.18970,18.36816,30.200,551.398,75.640,296.445 ==> out/109.54297,18.39178.txt <== 2020-01-01,00,109.54297,18.39178,30.676,0.000,90.044,292.653 2020-01-01,01,109.54297,18.39178,28.187,355.642,86.229,294.425 2020-01-01,02,109.54297,18.39178,30.356,556.004,79.117,295.921 ==> out/109.89642,18.41394.txt <== 2020-01-01,00,109.89642,18.41394,30.581,0.000,89.560,293.056 2020-01-01,01,109.89642,18.41394,28.136,359.157,87.494,294.675 2020-01-01,02,109.89642,18.41394,29.953,558.076,82.460,295.942

oswll
質問者

お礼

iriyak様 早速のご回答ありがとうございました. >2020-*.txt はカンマで区切られたレコード。3列目 ($3) と 4列目 ($4) の値の組み合わせが lonlat.txt の<$1, $2>となっているレコードを抽出して、out/$1,$2.txt に格納したい。 まさにこの内容です!ありがとうございます. >コメントをくださったお二人へ 今日は朝からこのスクリプトと格闘していたため,帰宅いたします.明日早速実行させていただきます. 実は,私は修士2年の学生で,あるシミュレーションプログラムのアウトプットを解析しております.これで,なんとか進めそうです.ありがとうございました.

oswll
質問者

補足

すみません。最後の段階の awk -f target.awk 2020-*.txt で以下のようなエラーがでます。 .txt" for output (No such file or directory) なぜなのでしょうか。よろしくお願いします。

その他の回答 (4)

  • iriyak
  • ベストアンサー率48% (40/82)
回答No.5

データの連携ありがとうございます。 現状、target.awk があるべき姿のものになっていないため、派生事象として Not such file or directory が出ているようです。 > "out/109.18970,18.36816.txtとなっていないのがエラーの原因でしょうか。そうしますと、gen.awkを編集する必要があるのでしょうか。 はい。Next Action は gen.awk がなぜ次のように To Be (あるべき姿) のようにはなっていないか、gen.awk 及び入力ファイル lonlat.txt を調べることになります。 (To Be) BEGIN { FS = "," } $3 == 109.18970 && $4 == 18.36816 { print >> "out/109.18970,18.36816.txt" } $3 == 109.54297 && $4 == 18.39178 { print >> "out/109.54297,18.39178.txt" } $3 == 109.89642 && $4 == 18.41394 { print >> "out/109.89642,18.41394.txt" }   :   : (Actual) BEGIN { FS = "," } .txt" }t >> "out/109.18970,18.36816 .txt" }t >> "out/109.54297,18.39178 .txt" }t >> "out/109.89642,18.41394   :   : (Quick Review) To Be と Actual を比べてみると、gen.awk がうまくいっている所とそうでないところの両方が出力結果から観測できます。gen.awk #★の行は結果からうまくいっているようです。lonlat.txt の $1, $2 の切り出しも成功している。gsub も out/109.89642,18.41394 のように表示されていることから /key1/, /key2/ の置き換えも成功している。それ以外ですね。変数 s に代入されている値がそもそも意図しないものなのか。それとも質問者の Awk では gsub の振舞いが回答者の Awk のそれとは異なるからか。そもそも質問者の gen.awk ≠ 回答者の gen.awk であるからか。gsub の前後で逐次 s の値を表示して実際の動きを確認し、To Be に近づけていく作業を継続していきましょう。 BEGIN { FS = "," #★ print "BEGIN { FS = \",\" }" #★ } { key1 = $1 #★ key2 = $2 #★ s = "$3 == key1 && $4 == key2 { print >> \"out/key1,key2.txt\" }" gsub(/key1/, key1, s) gsub(/key2/, key2, s) print s } (Awk を学ぶために) No.1, 2 は書籍で、No.3 はウェブ・リソースです。No.1 を特にお勧めしたいです。 1. プログラミング言語AWK (新紀元社情報工学シリーズ) A. V. エイホ、P. J. ワインバーガー、B. W. カーニハン 2. sed&awkプログラミング (単行本) デール ドゥラティ (著), アーノルド ロビンス (著), Dale Dougherty (原著), Arnold Robbins (原著), 福崎 俊博 (翻訳) 3. スクリプティング言語資料室(仮) 幾つかの言語に関する資料/ポインター から Awk http://www.kt.rim.or.jp/~kbk/

oswll
質問者

お礼

iriyak様 コメントありがとうございます。 とにかく、To be になるようにgen.awkを編集し、リトライを続けていきます。成功したときうれしいですからね! とにかく成功しましたら、原因とソースを掲示します。なるべく今日中には完了させたいです。 なお、プログラミング言語AWKはAmazonにて購入しました。ありがとうございます。

  • iriyak
  • ベストアンサー率48% (40/82)
回答No.4

> .txt" for output (No such file or directory) もう少し手かがかりが欲しいところです。 head -10 target.awk の結果および awk -f target.awk 2020-*.txt の結果をコマンドラインで実行を指示する所から表示された近辺をすべて切り取って提供は可能でしょうか。 生成された target.awk の中で書きだす先のファイル名が .txt" であり No such file or directory そういうファイル名のファイルは存在しないから継続できないと警告しているように見えます。 それから、今後は Awk のプログラミング言語特有の用語が出現します。並行して Awk 自身の技術調査も進めてキャッチアップをトライください。

oswll
質問者

お礼

解決しました。 原因はWindowsとLinuxの共有利用でした。 latlon.txtはWindows上で作ったため、改行コードがCRLFになっていました。 これを参照URLにありますnkfのコマンドでUTF8+LFに変換しましたら、無事通りました。Linuxは初心者のため,VMwareを用い両方のOSで処理していたことが原因になっていました。もちろん、スクリプトに問題はありません。それでは、研究を進めていこうと思います。この度は、ご丁寧に面倒をみていただきありがとうございました。 参照URL: http://archive.mag2.com/0000242266/20080214080000000.html

oswll
質問者

補足

ご回答ありがとうございます。結果は以下のようになっています。 CSM@ubuntu-vm:/mnt/hgfs/OP/2020/test5$ head -10 target.awk BEGIN { FS = "," } .txt" }t >> "out/109.18970,18.36816 .txt" }t >> "out/109.54297,18.39178 .txt" }t >> "out/109.89642,18.41394 .txt" }t >> "out/108.80933,18.67845 .txt" }t >> "out/109.16388,18.70372 .txt" }t >> "out/109.51874,18.72752 .txt" }t >> "out/109.87378,18.74982 .txt" }t >> "out/110.22900,18.77063 .txt" }t >> "out/108.78174,19.01466 CSM@ubuntu-vm:/mnt/hgfs/OP/2020/test5$ awk -f target.awk 2020-*.txt .txt" for output (No such file or directory) 以上のようになっております。"out/109.18970,18.36816.txtとなっていないのがエラーの原因でしょうか。そうしますと、gen.awkを編集する必要があるのでしょうか。このコメントを送信後試してみます。 Linuxの本を持っていますが、どれも入門書のようでこのような応用タイプの事例が載っていないため、Google等の検索で頑張ってみましたが見つかりませんでした。ご指摘のとおり、いつまでも教えて君はいけないので技術調査を進めていきます。

  • iriyak
  • ベストアンサー率48% (40/82)
回答No.3

> 実は,私は修士2年の学生で,あるシミュレーションプログラムのアウトプットを解析しております.これで,なんとか進めそうです. よかったですね、がんばってください。 話はかわりますが、こうした Data Processing に Awk は役立ちますので、これを機にプログラミング言語 Awk の習得をトライください♪

oswll
質問者

補足

すみません。最後の段階の awk -f target.awk 2020-*.txt で以下のようなエラーがでます。 .txt" for output (No such file or directory) なぜなのでしょうか。よろしくお願いします。

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.1

>同じ行数の文字列を抽出し という部分が意味不明です。grepを使っているようですが、「これこれの文字列を含んだ行を抽出し」なのでしょうか?その場合の「これこれ」とは? 「同じ行数」という語から、先頭の何行かを取り出すのかとも思いましたが、そうでもなさそうだし。 他人に手作業を指示して出来るレベルの具体性で、やりたいことを書いてください。

oswll
質問者

補足

notnot様 ご回答ありがとうございます.不明瞭な説明で申し訳ございませんでした.引き続き,ご協力のほどよろしくお願い申し上げます. >同じ行数の文字列を抽出し とは,テキストデータの同じ行のことです. 全テキストデータ(8784個)から1行目なら1.txt,2行目なら2.txt,3行目なら3.txt・・・・(5712行まであります)といった具合に各テキストデータから抽出して,下のディレクトリに出力したいのです.つまり,出力されるテキストデータは5712個で各々が8784行になるはずです.・・・(1) notnot様が混乱なさってしまったのは,私が作ったスクリプトが「これこれの文字列を含んだ行を抽出する」ものであったからです.単純に上記のようなプログラムを作成すればよかったのですが,できなかったので,あのようなスクリプトを掲載しました. 私としましては,(1)に示しました方法で処理したいのですが,教えていただけないでしょうか.周りにプログラムが書ける人が居なくて困っております.よろしくお願いします.

関連するQ&A