如何使用开始和结束位置分隔文本文件的值

时间:2016-09-16 10:08:12

标签: ruby csv hash

我有一个文本文件:

GLKIIM 08052016 08052016 444-22222222 33333 5675555
ABCDEF 87645123 34211016 333-11111111 22222 5123455

我正在使用CSV.read来阅读文本文件。

对于文本文件中的每一行,我需要通过开始和结束位置提取列值。为此,我有阵列:

start_pos = [1 8 17 26 30 39 45]
end_pos = [6 15 24 28 37 43 51]

表示从位置start_pos[0]end_pos[0]的文本文件,即1到6,我们将拥有第一列的值GLKIIM和{{1} }。

列名是:

ABCDEF

我需要创建一个哈希,如下所示:

column_name = [SOURCE_NAME BATCH_DATE EFFECT_DATE ID ACCOUNT_NO ENTITY ACCOUNT]

我不能使用空格({ 0=>{"SOURCE_NAME"=>"GLKIIM", "BATCH_DATE"=>"08052016", "EFFECT_DATE"=>"08052016", "ID"=>"444", "ACCOUNT_NO"=>"22222222", "ENTITY"=>"33333", "ACCOUNT"=>"5675555"}, 1=>{"SOURCE_NAME"=>"ABCDEF", "BATCH_DATE"=>"87645123", "EFFECT_DATE"=>"34211016", "ID"=>"333", "ACCOUNT_NO"=>"11111111", "ENTITY"=>"22222", "ACCOUNT"=>"5123455"} } )作为分隔符来分隔列值,我需要使用开始和结束位置。

3 个答案:

答案 0 :(得分:1)

不要将文件作为逗号分隔值(CSV)文件读取,如果它不是。 使用"说代码"您可以使用File.readlines代替:

#!/bin/env ruby

result = ARGF.readlines.map do |line|                                     
  [line[0..5], line[7..14], line[16..23], line[24..36]]                   
end                                                                       

puts result.inspect
# => [["GLKIIM", "08052016", "08052016", " 444-22222222"], ["ABCDEF", "87645123", "34211016", " 333-11111111"]]

如果您保存此脚本,则可以将其运行为:

readliner.rb MYFILE.TXT MYFILE2.TXT MYFILE3.TXT

或管道:

cat myfile | readliner.rb

或者使用

File.readlines("MYFILE.TXT")
脚本中的

而不是ARGF.readlinesreadlines的使用可能会带来问题,因为它将整个文件读入内存以产生一系列行。有关该主题的小型讨论,请参阅评论。

让代码高尔夫一点,同时保持一定的可读性并删除readlines

#!/bin/env ruby

COLS = { "SOURCE_NAME" => 0..5,
         "BATCH_DATE"  => 7..14,
         "EFFECT_DATE" => 16..23 }

result = ARGF.each_with_index.map do |line, idx|
  [idx, COLS.map{|name,range| [name, line[range]] }.to_h ]
end.to_h

puts result.inspect
# => {0=>{"SOURCE_NAME"=>"GLKIIM", "BATCH_DATE"=>"08052016", "EFFECT_DATE"=>"08052016"}, 1=>{"SOURCE_NAME"=>"ABCDEF", "BATCH_DATE"=>"87645123", "EFFECT_DATE"=>"34211016"}}

答案 1 :(得分:1)

input = 'GLKIIM 08052016 08052016 444-22222222 33333 5675555
ABCDEF 87645123 34211016 333-11111111 22222 5123455'
start_pos = %w|1 8 17 26 30 39 45|.map &:to_i
end_pos   = %w|6 15 24 28 37 43 51|.map &:to_i

input.split($/).map do |line|
  start_pos.zip(end_pos).map { |s, e| line[s-1..e-1] }
end
#⇒  [["GLKIIM", "08052016", "08052016", "444", "22222222", "33333", "5675555"],
#    ["ABCDEF", "87645123", "34211016", "333", "11111111", "22222", "5123455"]]

答案 2 :(得分:0)

我使用下面的代码:

file = File.open('abc.TXT', "r")
i = 0
file.each_line do |line|
    temp = {}
    for itrator in 0..column_name.length-1
          temp[column_name[itrator]] = line[start_pos[itrator]-1..end_pos[itrator]-1]
        end
        data_hash[i] = temp
        i+=1
      end
puts data_hash

假设包含以下数据的文件名为abc.txt

GLKIIM 08052016 08052016 444-22222222 33333 5675555
ABCDEF 87645123 34211016 333-11111111 22222 5123455