我正在努力解决如何从Ruby CSV中获取当前的行号.这是我的代码:

options = {:encoding => 'UTF-8', :skip_blanks => true}
CSV.foreach("data.csv", options, ) do |row, i|
   puts i
end

但这似乎并不像预期的那样有效.有办法做到这一点吗?

推荐答案

Because of changes in CSV in current Rubies, we need to make some changes. See farther down in the answer for the original solution with Ruby prior to 2.6. and the use of 100 which continues to work regardless of the version.

For 2.6+ this'll work:

require 'csv'

puts RUBY_VERSION

csv_file = CSV.open('test.csv')
csv_file.each do |csv_row|
  puts '%i %s' % [csv_file.lineno, csv_row]
end
csv_file.close

如果我读到:

Year,Make,Model,Description,Price
1997,Ford,E350,"ac, abs, moon",3000.00
1999,Chevy,"Venture ""Extended Edition""","",4900.00
1999,Chevy,"Venture ""Extended Edition, Very Large""","",5000.00
1996,Jeep,Grand Cherokee,"MUST SELL!\nair, moon roof, loaded",4799.00

代码将产生以下输出:

2.6.3
1 ["Year", "Make", "Model", "Description", "Price"]
2 ["1997", "Ford", "E350", "ac, abs, moon", "3000.00"]
3 ["1999", "Chevy", "Venture \"Extended Edition\"", "", "4900.00"]
4 ["1999", "Chevy", "Venture \"Extended Edition, Very Large\"", "", "5000.00"]
5 ["1996", "Jeep", "Grand Cherokee", "MUST SELL!\\nair, moon roof, loaded", "4799.00"]

更改是因为我们必须访问当前文件句柄.以前我们可以使用global $.,它总是有失败的可能性,因为global可能会被调用代码的其他部分踩到.如果我们有被打开文件的句柄,那么我们可以使用lineno而不必担心这个问题.


$.

Ruby prior to 2.6 would let us do this:

Ruby有一个magic variable $.,它是正在读取的当前文件的行号:

require 'csv'

CSV.foreach('test.csv') do |csv|
  puts $.
end

我得到上面的代码:

1
2
3
4
5

$INPUT_LINE_编号

Perl中始终使用$..在Ruby中,建议我们使用以下方法来避免其"神奇"的一面:

require 'english'

puts $INPUT_LINE_编号

如果有必要处理字段中的嵌入线端,只需稍加修改即可轻松处理.假设CSV文件"test.CSV"包含一行,其中嵌入了新行:

Year,Make,Model,Description,Price
1997,Ford,E350,"ac, abs, moon",3000.00
1999,Chevy,"Venture ""Extended Edition""","",4900.00
1996,Jeep,Grand Cherokee,"MUST SELL!
air, moon roof, loaded",4799.00
1999,Chevy,"Venture ""Extended Edition, Very Large""","",5000.00

带_的索引

使用Enumerator's 带_的索引(1)可以很容易地跟踪CSV向块的屈服次数,有效地模拟使用$.,但在读取处理线端所需的额外行时,尊重CSV的工作:

require 'csv'

CSV.foreach('test.csv', headers: true).带_的索引(1) do |row, ln|
  puts '%-3d %-5s %-26s %s' % [ln, *row.values_at('Make', 'Model', 'Description')]
end

运行时,输出:

$ ruby test.rb
1   Ford  E350                       ac, abs, moon
2   Chevy Venture "Extended Edition"
3   Jeep  Grand Cherokee             MUST SELL!
air, moon roof, loaded
4   Chevy Venture "Extended Edition, Very Large"

Ruby相关问答推荐

Ruby将字符串中的反斜杠替换为双反斜杠

清理 jruby 中输入数据的编码错误

Ruby - 使用索引值识别和更新数组中的重复项

使用 Sorbet RBI 时需要 Elem

类 SpecificationPolicy 的超类不匹配

使用 Drive API 创建空文件

如何从 DateTime 值中删除区域?

你如何称呼 Ruby 中的 &: 运算符?

如果 Java 人go Scala,C# go F#,那么 Ruby 人go 哪里寻求函数式?

bundler 可以告诉我 Gemfile 中的哪些 gem 有更新的版本

ruby 是否支持 case 语句中的范围?

如何在 Ruby 中使用 (n) 诅咒?

Ruby:继承与类变量一起工作的代码

Ruby - 查看端口是否打开

RSpec:我如何在期望语法中使用数组包含匹配器

Ruby,生成随机十六进制 colored颜色

如何使用密码保护我的 /sidekiq 路由(即需要对 Sidekiq::Web 工具进行身份验证)?

Ruby总是Round Up

Ruby 疯狂:类与对象?

Ruby:如何在不指向同一个对象的情况下复制变量?