Extract data from Ruby from a text file

I have a relatively large text file with data blocks selected as follows:

ANALYSIS OF X SIGNAL, CASE: 1 TUNE X = 0.2561890123390808 Line Frequency Amplitude Phase Error mx my ms p 1 0.2561890123391E+00 0.204316425208E-01 0.164145385871E+03 0.00000000000E+00 1 0 0 0 2 0.2562865535359E+00 0.288712798671E-01 -.161563284233E+03 0.97541196785E-04 1 0 0 0 

(they contain more lines and then repeat)

First, I would like to extract the numeric value after TUNE X = and output them to a text file. Then I would like to extract the numeric value of LINE FREQUENCY and AMPLITUDE as a pair of values ​​and output them to a file.

My question is this: although I could do something more unemployed using simple REGEXP, I'm not sure if this is the right way to do this, and I would like some tips or code examples to show how I can do this effective with Ruby.

+6
ruby
source share
4 answers

Generally (not verified)

 toggle=0 File.open("file").each do |line| if line[/TUNE/] puts line.split("=",2)[-1].strip end if line[/Line Frequency/] toggle=1 next end if toggle a = line.split puts "#{a[1]} #{a[2]}" end end 

Go through the file line by line, check / TUNE /, then split "=" to get the last item. Do the same for the lines containing / Line Frequency / and set the switch flag to 1. This means that the rest of the line contains the data you want to receive. Since the frequency and amplitude are in fields 2 and 3, they are split along the lines and get the corresponding positions. This is usually an idea. As for the switch, you can set the toggle flag to 0 in the next block using a template (e.g. SIGNAL CASE or ANALYSIS)

+3
source share

There are many ways to do this. This is a simple first pass:

 text = 'ANALYSIS OF X SIGNAL, CASE: 1 TUNE X = 0.2561890123390808 Line Frequency Amplitude Phase Error mx my ms p 1 0.2561890123391E+00 0.204316425208E-01 0.164145385871E+03 0.00000000000E+00 1 0 0 0 2 0.2562865535359E+00 0.288712798671E-01 -.161563284233E+03 0.97541196785E-04 1 0 0 0 ANALYSIS OF X SIGNAL, CASE: 1 TUNE X = 1.2561890123390808 Line Frequency Amplitude Phase Error mx my ms p 1 1.2561890123391E+00 0.204316425208E-01 0.164145385871E+03 0.00000000000E+00 1 0 0 0 2 1.2562865535359E+00 0.288712798671E-01 -.161563284233E+03 0.97541196785E-04 1 0 0 0 ANALYSIS OF X SIGNAL, CASE: 1 TUNE X = 2.2561890123390808 Line Frequency Amplitude Phase Error mx my ms p 1 2.2561890123391E+00 0.204316425208E-01 0.164145385871E+03 0.00000000000E+00 1 0 0 0 2 2.2562865535359E+00 0.288712798671E-01 -.161563284233E+03 0.97541196785E-04 1 0 0 0 ' require 'stringio' pretend_file = StringIO.new(text, 'r') 

This gives us a StringIO object that we can pretend to be a file. We can read from it line by line.

I changed the numbers a bit to make it easier to see how they are written in the output.

 pretend_file.each_line do |li| case when li =~ /^TUNE.+?=\s+(.+)/ print $1.strip, "\n" when li =~ /^\d+\s+(\S+)\s+(\S+)/ print $1, ' ', $2, "\n" end end 

For real use, you want to change the print statements to a file descriptor: fileh.print

The result is as follows:

 # >> 0.2561890123390808 # >> 0.2561890123391E+00 0.204316425208E-01 # >> 0.2562865535359E+00 0.288712798671E-01 # >> 1.2561890123390808 # >> 1.2561890123391E+00 0.204316425208E-01 # >> 1.2562865535359E+00 0.288712798671E-01 # >> 2.2561890123390808 # >> 2.2561890123391E+00 0.204316425208E-01 # >> 2.2562865535359E+00 0.288712798671E-01 
+1
source share
 file = File.open("data.dat") @tune_x = @frequency = @amplitude = [] file.each_line do |line| tune_x_scan = line.scan /TUNE X = (\d*\.\d*)/ data_scan = line.scan /(\d*\.\d*E[-|+]\d*)/ @tune_x << tune_x_scan[0] if tune_x_scan @frequency << data_scan[0] if data_scan @amplitude << data_scan[0] if data_scan end 
+1
source share

You can read the file line by line and cut each one by the character number, for example:

  • extract tune x get characters from 10 to 27 on line 2
  • extract LINE FREQUENCY get characters from 3 to 22 on line 6+n
0
source share

All Articles