我是ruby的新手,并且有以下代码读取文件,然后将符号分隔为“|”登录Struc数据类型的不同属性:
Song = Struct.new(:title, :name, :length)
song_file = File.new("songdata.txt")
songs = []
song_file.each_line do |line|
file, length, name, title = line.chomp.split(/\s*\|\s*/)
songs << Song.new(title, name, length)
end
p songs
文件songdata.txt包含以下txt:
/jazz/j00132.mp3 | 3:45 | Fats Waller | Ain't Misbehavin'
/jazz/j00319.mp3 | 2:58 | Louis Armstrong | Wonderful World
/bgrass/bg0732.mp3| 4:09 | Strength in Numbers | Texas Red
但是,当我去打印阵列歌曲时,它只包含文本文件的第一行。有关为什么会这样的想法?
答案 0 :(得分:1)
问题应该与行结尾有关。 Ruby似乎可以正确地处理Windows和Unix行结尾,但只有在您将文件的行结束更改为OSX时才会读取第一行(&#34; Mac OS 9&#34;在SublimeText中)
将songdata.txt
的行结尾更改为Unix或Windows。
答案 1 :(得分:0)
试试这个
arr = []
File.open('songdata.txt', 'r') do |song_file|
song_file.each_line do |detail|
arr = detail.split(' | ')
title = arr[0].split(/\s*\|\s*/)
length = arr[1]
artist = arr[2]
name = arr[3]
#now you can do anything as per requirement
end
end
答案 2 :(得分:0)
看起来这个问题是由于行结尾造成的。我发布此信息只是为了向您展示如何在此用例中使用map
。它还使用__END__
和DATA
在单个ruby脚本中混合ruby代码和测试数据。适合测试此类案例。
Song = Struct.new(:title, :name, :length)
song_file = DATA
songs = song_file.each_line.map do |line|
file, length, name, title = line.chomp.split(/\s*\|\s*/)
Song.new(title, name, length)
end
p songs.size
__END__
/jazz/j00132.mp3 | 3:45 | Fats Waller | Ain't Misbehavin'
/jazz/j00319.mp3 | 2:58 | Louis Armstrong | Wonderful World
/bgrass/bg0732.mp3| 4:09 | Strength in Numbers | Texas Red
通过使用map
,您可以避免在迭代文件之前定义空数组。
答案 3 :(得分:0)
正如之前所说过的类似问题,您可能不应该自己进行解析,而是使用CSV库为您完成。 CSV =逗号分隔值,但支持除逗号以外的分隔符,并且管道很常见。
Ruby有一个内置的CSV库,使用它,您可以使用以下代码比较您的方法和CSV方法的结果:
#!/usr/bin/env ruby
Song = Struct.new(:title, :name, :length)
SONG_FILESPEC = 'songdata.txt'
def read_records_regex # OP's original approach
songs = []
File.new(SONG_FILESPEC).each_line do |line|
file, length, name, title = line.chomp.split(/\s*\|\s*/)
songs << Song.new(title, name, length)
end
songs
end
require 'csv'
def read_records_csv # alternate CSV approach
songs = []
CSV.foreach(SONG_FILESPEC, col_sep: '|') do |fields|
fields.map!(&:strip)
file, length, name, title = fields
songs << Song.new(title, name, length)
end
songs
end
puts read_records_regex
puts '-' * 79
puts read_records_csv
输出:
#<struct Song title="Ain't Misbehavin'", name="Fats Waller", length="3:45">
#<struct Song title="Wonderful World", name="Louis Armstrong", length="2:58">
#<struct Song title="Texas Red", name="Strength in Numbers", length="4:09">
-------------------------------------------------------------------------------
#<struct Song title="Ain't Misbehavin'", name="Fats Waller", length="3:45">
#<struct Song title="Wonderful World", name="Louis Armstrong", length="2:58">
#<struct Song title="Texas Red", name="Strength in Numbers", length="4:09">
请注意,如果要丢弃数据文件,则该文件可能不应有空格。
有些CSV内核比Ruby的内置支持更复杂,但这种情况很简单,Ruby很好。