从文本文件中提取Ruby数据

时间:2011-04-01 07:53:01

标签: ruby

我有一个相对较大的文本文件,其数据块分层如下:

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

(它们包含更多行然后重复)

我想首先在TUNE X =之后提取数值并将其输出到文本文件中。然后我想将LINE FREQUENCYAMPLITUDE的数值作为一对值提取并输出到文件中。

我的问题如下:尽管我可以使用一个简单的REGEXP做一些无用的工作我不相信这是正确的方法,我想要一些建议或代码示例来说明我如何有效地做到这一点用Ruby。

4 个答案:

答案 0 :(得分:3)

一般来说,(未经测试)

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

逐行浏览文件,检查/ TUNE /,然后拆分“=”以获取最后一项。 对包含/ Line Frequency /的行执行相同操作,并将切换标志设置为1.这表示行的其余部分包含您要获取的数据。由于频率和幅度在场2和3处,然后在线上分开并获得相应的位置。一般来说,这就是主意。对于切换,您可能希望使用模式在下一个块中将切换标志设置为0(例如SIGNAL CASE或ANALYSIS)

答案 1 :(得分:1)

有很多方法可以做到这一点。这是一个简单的第一步:

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')

这给了我们一个StringIO对象,我们可以假装它是一个文件。我们可以通过线条阅读。

我稍微更改了数字,以便更容易看到它们在输出中被捕获。

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

对于实际使用,您需要将print语句更改为文件句柄:fileh.print

输出如下:

# >> 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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

您可以逐行阅读文件,并按符号编号剪切,例如:

  • 从中提取tune x获取符号 第2行10至27日
  • 提取LINE FREQUENCY得到 6+n
  • 上3到22号的符号