
rubyを用いたプログラムで、複数列のデータを1行にまとめる方法を知りたいです。
rubyというプログラムの勉強中です。
テキストファイルの出力に関してなのですが、質問させてください。以下の様なデータがあり、一列当たりはスペース含め40文字で区切られているprnファイルであります。
それを縦方向に積み重ねていくというプログラムを組もうとしました。以下がその例です。
1,2,1, 2,2,1, 3,2,1,
X方向_変位 0.01 X方向_変位 0.02 X方向_変位 0.03
0,0,0, 0,0,0, 0,0,0,
2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
1,2,2,7, 1,2,2,7, 1,2,2,7,
0,1,1, 0,1,1, 0,1,1,
1,data1, 1,data2, 1,data3,
2,data1, 2,data2, 2,data3,
3,data1, 3,data2, 3,data3,
4,data1, 4,data2, 4,data3,
5,data1, 5,data2, 5,data3,
6,data1, 6,data2, 6,data3,
7,data1, 7,data2, 7,data3,
8,data1, 8,data2, 8,data3,
9,data1, 9,data2, 9,data3,
10,data1, 10,data2, 10,data3,
11,data1, 11,data2, 11,data3,
12,data1, 12,data2, 12,data3,
13,data1, 13,data2, 13,data3,
14,data1, 14,data2, 14,data3,
15,data1, 15,data2, 15,data3,
-1,0, -1,0, -1,0,
であります。(スペース区切りの前にカンマがありますが、これは区切り文字ではなく、あくまでスペースで区切られております)イメージしやすいように、図を添付させていただきます。列の長さは不定であり、データ列間は半角スペースのみで区切られております。
上記のようなデータを
1,2,1,
X方向_変位 0.01
0,0,0,
2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
1,2,2,7,
0,1,1,
1,data1,
2,data1,
3,data1,
4,data1,
5,data1,
6,data1,
7,data1,
8,data1,
9,data1,
10,data1,
11,data1,
12,data1,
13,data1,
14,data1,
15,data1,
-1,0,
2,2,1,
X方向_変位 0.02
0,0,0,
2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
1,2,2,7,
0,1,1,
1,data2,
2,data2,
3,data2,
4,data2,
5,data2,
6,data2,
7,data2,
8,data2,
9,data2,
10,data2,
11,data2,
12,data2,
13,data2,
14,data2,
15,data2,
-1,0,
3,2,1,
X方向_変位 0.03
0,0,0,
2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
1,2,2,7,
0,1,1,
1,data3,
2,data3,
3,data3,
4,data3,
5,data3,
6,data3,
7,data3,
8,data3,
9,data3,
10,data3,
11,data3,
12,data3,
13,data3,
14,data3,
15,data3,
-1,0,
4,2,1,
X方向_変位 0.04
0,0,0,
2,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
1,2,2,7,
0,1,1,
1,data4,
2,data4,
3,data4,
4,data4,
5,data4,
6,data4,
7,data4,
8,data4,
9,data4,
10,data4,
11,data4,
12,data4,
13,data4,
14,data4,
15,data4,
-1,0,
以下続く
と重ねたいという意味です。
自分で組んだところ、一列目のみが出力されて、二列目三列目のデータが出力されませんでした。
二列目以降がうまく取得できていないのですが、サンプルというよりはこのように組めば大丈夫というプログラムの答えが知りたいです。なお、本当のファイルは横に多いと1000列で1万行近くになります。そのため、私が一番得意なVBAでは作業ができず困っております。巨大なファイルが操れるrubyやphysonならできるのではないかと思っての質問です。
この完成したファイルをファイル②とすると、その前にファイル①を加え、ファイル②の後ろにファイル③を付け加えたファイル完成版というのを作ることも可能なのでしょうか?というのも、とてつもなくファイルが大きくなってテキストエディタではファイル②を編集することも困難になりそうだからです。
よろしくお願いします。

No.3ベストアンサー
- 回答日時:
No.1です。
先の回答に誤りがありましたので修正しました、失礼しました。
> 変位と0.01の間にはスペースではなく、[_](アンダーバー)でありました。
であれば、もっと単純なプログラムになります。
--------------------
#coding: utf-8
Encoding.default_external = 'utf-8'
ary = Array.new
File.foreach("input.txt") do |line|
line.chomp!
ary.push(line.split)
end
File.open("output.txt",'w') do |fo|
ary[0].size.times do |i|
ary.each { |e| fo.puts e[i] }
end
end
--------------------
1行目をプログラムファイル(a.rb)の文字コード
2行目を読み込むデータファイル(input.txt/test.txt)の文字コードにしてみてください。
※もし更に不明点がありましたら、上記文字コード情報およびRubyのバージョンも併せてご提示ください。
No.5
- 回答日時:
上手くいった様で何よりでした。
> splitで何をやっているのかが分かりません。
これはVBAのSplit関数と同じで、文字列を特定の記号で分割して配列にします。
今回の様に特定の記号を指定しない場合はスペースで区切ることになります。
従ってaryには、ご質問のデータでいうと1行を3分割した配列が格納されます。
(aryは二次元?配列になります)
> |fo|ってどのような意味を示しているのですか?
これはVBAの、Open "output.txt" For Output As #1 の#1と同じと思ってもらえれば良いです。
ですから、fo.puts "hoge" は、VBAのPrint #01, "hoge" と同じになります。
> ary[0].size.times do |i| →ここで配列0から[i]まで繰り返せという命令ですが、
> |i|の引数はどこから引っ張ってきているのですか?
ary[0]にはデータ1行目を3分割した配列なので、ary[0].size は 3です。
( VBAのUBound(ary)と似た感じです。)
そして、3.times は do ~ endを3回繰り返すという意味で、
変数iには回数(0~2 = 出力する列番号)が入ります。
> ary.each { |e| fo.puts e[i] } →ここでの|e|は何を引数としているのか。
ary[0]はデータ1行目を3分割した配列、ary[1]はデータ2行目を3分割した配列……となります。
ary.eachでaryの各要素を{……}に渡します、その時変数eに各要素(各行を3分割した配列)が代入されます。
> puts e[i]が何を表しているのか。
変数eは各行を3分割した配列なので、e[i]は、その行のi列目の文字列になります。
> 参考書としてどのようなものを参考にされていましたか?
最初に購入したのは「たのしいRuby」ですね、今も定番の入門本です(当時は初版でしたが…)
あとは、マニュアルを見たり、ネットで検索したり、自分で試行錯誤したりですね。
ドキュメント入手先:
https://www.ruby-lang.org/ja/documentation/
私も業務でテキストデータ加工用にRubyを使用しています。
(最近はいろいろありVBAやPowerShellに移行途上ですけど)
Rubyの文法はVBAとくらべるとちょっと風変わりに見えますが
基本文法、データ構造と正規表現を習得すれば、
ちょっとしたプログラムなら、すごく楽に書けるので重宝します。
VBAの方でどのようなものと同じなのかを教えていただいたため、非常にわかりやすかったです。
たのしいRubyは購入し勉強してみようと思います。入門からやらないと初めてのはとてもとても。
VBAで動かすためには今回のはファイルが大きすぎておとなしく作業してくれず、困っていたところ
siffon9様にはお忙しいところ、助けていただき感謝します。
No.4
- 回答日時:
No.1,3です。
> 5)に関しては、空白部分を削除してもらえる方が、データが少し軽くなるのでありがたいです。
この部分を読み漏らしていました。
line.chomp! の後に
line.strip! を追加してください。
研究室にいけないため、質問に投稿したデータで試してみました。
testデータでは文字コードをShift_JISで投稿したデータは変換できました。
解析マシンの方はLinuxであるため文字コードはutf-8になっているのかShift_JISになっているのか
下宿先からでははっきりしませんので、現場でうまく動かなかったらコードを変えてみます。
おかげさまで実験や論文がはかどりそうです。
少し教えてください。
構文で
File.foreach("input.txt") do |line| →ファイルを一行ずつ読み込み最後まで繰り返せという命令
line.chomp! →改行文字を取り除いて行を読めという命令
ary.push(line.split) →配列に行を追加記述しろという意味だと思うのですが、splitで何をやっているのかが分かりません。
File.open("output.txt",'w') do |fo| →ここで書きこみ可能状態でoutput.txtを作成し|fo| を繰り返せという意味だと思うのですが|fo| ってどのような意味を示しているのですか?
ary[0].size.times do |i| →ここで配列0から[i]まで繰り返せという命令ですが、|i|の引数はどこから引っ張ってきているのですか?
ary.each { |e| fo.puts e[i] } →ここでの|e|は何を引数としているのか。puts e[i]が何を表しているのか。
です。VBAと全く構造が違うんですね。解読するまでに楽しそうですけど、色々と時間がかかりそうです。
研究室内ではvbaとrubyしか使えないためにrubyも覚えようと思っているのですが、参考書としてどのようなものを参考にされていましたか?特に、このようなテキストファイル編集用重視が嬉しいです。

No.2
- 回答日時:
幾つか補足要求があります。
1)ファイルのデータの文字コード(漢字)はシフトJISですか、それとも他の文字コードですか?
(EUC,utf-8等)
以下、文字コードが、シフトJISでの前提での質問です。
以下の前提であってますか。
2)1行の長さ(改行コードを含めない)は40バイトの整数倍である。
3)1行の長さは全行同一である。
4)各列は40バイトなので、空白で区切るのではなく、40バイト単位で区切り、それを出力ファイルへ出力すればよい。
5)出力ファイルへ出力時、後ろの空白は削除しない。(1行40バイトで出力する)
尚、ファイル①とファイル②とファイル③を付け加えたものを作成する場合は、コマンドプロンプトで
copy ファイル① + ファイル② + ファイル③ ファイル④
とすればOKです。
ファイル④がファイル①とファイル②とファイル③を付けえたファイルになります。
No.1
- 回答日時:
こんな感じでどうでしょう。
input.txtを読んで、output.txtを出力します。
※この掲示板での段付け表示の為、行頭に全角スペースをいれているのでご注意下さい。
ary = Array.new
File.foreach("input.txt") do |line|
line.chomp!
if /^X方向/ =~ line
d = line.split
a = Array.new
(d.size/2).times do |i|
a.push(d[i*2] + " " + d[i*2+1])
end
ary.push(a)
else
ary.push(line.split)
end
end
File.open("output.txt",'w') do |fo|
ary.size.times do |i|
ary.each { |e| fo.puts e[i] }
end
end
> この完成したファイルをファイル②とすると、その前にファイル①を加え、
> ファイル②の後ろにファイル③を付け加えたファイル完成版というのを作ることも可能なのでしょうか?
出力用にファイル4をopenして、ファイル1,2,3を順番に出力してゆけば可能だと思います。
ただ巨大なファイルでそのようなことを行ったことがないのでサイズ的な面で可能かはわかりません。
提示していただき感謝いたします。
そして、すみません。「X方向_変位 0.01」などの部分ですが、変位と0.01の間にはスペースではなく、[_](アンダーバー)でありました。その場合は
if /^X方向/ =~ line
d = line.split
a = Array.new
(d.size/2).times do |i|
a.push(d[i*2] + " " + d[i*2+1])
end
ary.push(a)
の部分をカット、あるいは修正が必要になるのでしょうか?
(インフルエンザにかかってしまったため、木曜日まで研究室に行けなくなってしまったため実際の動作確認がそこからです。)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) pandasでまとめてインデックスを削除するにはどうすればいいですか? たとえば、以下のプログラムで 1 2022/07/31 23:09
- その他(プログラミング・Web制作) Fortranでの出力ファイル 2 2023/03/21 21:25
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- UNIX・Linux Linuxについて質問です。 以下のような設定をしたMakefileを作成するにはどう記述すればよい 1 2023/02/03 20:10
- その他(プログラミング・Web制作) google formsを使ったタスク依頼フォーム作成におけるご相談 1 2023/06/22 15:55
- MySQL MYSQL エラー 2 2022/10/18 11:37
- Java JaneStyleのスレッドが見れなくなった 1 2023/06/10 08:02
- JavaScript EasyUIのSubGrid(jquery)におけるObjectに入れた連想配列について 1 2022/05/02 11:21
- 数学 行列の問題が分かりません。 3次正則行列Aの列ベクトル分割をA=(a1 a2 a3)とおくとき,次を 4 2022/06/23 08:34
- 数学 a1,a2, a3をベクトル空間Vのベクトルとする。a1+a2,a2+a3,a3+a1が一次独立のと 2 2022/10/02 15:55
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
While文を使って配列の中身を全...
-
行数が30万件ほどあるCSVから、...
-
PHP 引数渡しの文字化けについて
-
PHPでCSVの一部の行を編集したい
-
C言語でCSVファイルの行数を読...
-
CSVでアップロードしたデータの...
-
PHPからファイルをPOSTしたい
-
php Undefined variableエラー
-
CSVデータの行数カウントをした...
-
オブジェクトと文字列の比較
-
PHPで外部ファイルを読み込むと...
-
PHP:2つの置換文字列を一気に...
-
文字列変換について
-
特定部分を書き換え、他は現状...
-
PHP、CSVファイルの日本語デー...
-
バイナリファイルの内容を、そ...
-
UTF-8のXMLがSJISのPHPで文字化け
-
PHPでの正規表現を使った文字列...
-
2次元配列のソート
-
PHPでサーバー上の書き換えたht...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
別ファイルの構造体の値を読み...
-
C言語でCSVファイルの行数を読...
-
Resource id #3 と表示されま...
-
【PHP】csvファイルへの書き出...
-
CSVファイルの最終行のデー...
-
行数が30万件ほどあるCSVから、...
-
自動で番号を振りたい
-
doxygenを使用する環境について
-
PHP検索ボックス複数設置
-
stdClass Objectを連想配列のよ...
-
ヒアドキュメントの中のfor文
-
PHP SimpleXml unsetについて
-
複数行のデータのPOST処理に関して
-
エラーメッセージ(無効な間接...
-
PHPでCSVの一部の行を編集したい
-
ログファイルの古い日付の行を...
-
配列同士の足し算のループ処理
-
多次元配列の一次元目の最大値...
-
文字列の文字一文字ずつを解析...
-
複数ファイルで、それぞれの行...
おすすめ情報
先ほど作っていただいたコードを、私が投稿いたしました文字列をtest.txtとして保存し
実行させたところ
C:\Users\ユーザーネーム\新しいフォルダー>ruby a.rb
a.rb:4: invalid multibyte char (UTF-8)
a.rb:4: invalid multibyte char (UTF-8)
a.rb:4: syntax error, unexpected end-of-input, expecting keyword_then or ';' or
'\n'
if /^?w????/ =~ line
というエラーが帰ってきてしまいました。(「X方向_変位 0.01」の部分はそのままです)
頭に# encoding: utf-8
を付ければうまくいくかと思いましたけど、そうではないみたいで・・・。
1)に関してはシフトjisです。
2)から4)に関してはその通りです
5)に関しては、空白部分を削除してもらえる方が、データが少し軽くなるのでありがたいです。
結合の事ですが、
copy test1.txt+test2.txt+test3.txt test4.txt
で結合されたtest4.txtが入手出来るということですか。コマンドプロンプトに便利な機能があるのですね。