Ruby字符串使用"\t"分割时会丢失"\n"

4
尝试分割这个制表符分隔的数据集:
171 1000    21  
269 1000    25  
389 1000    40  
1020    1-03    30  1
1058    1-03    30  1
1074    1-03    30  1
200 300     500

(为了更清晰:)
171\t1000\t21\t\n   
269\t1000\t25\t\n   
389\t1000\t40\t\n
1020\t1-03\t30\t1\n
1058\t1-03\t30\t1\n
1074\t1-03\t30\t1\n
200\t300\t\t500\n

a = text.split(/\n/)
a.each do |i|
  u = i.split(/\t/)
  puts u.size
end

==>
3
3
3
4
4
4
4

这个 \t\n 的组合似乎去掉了最后一个 \t,而我需要它来进一步导入。有什么方法可以解决这个问题吗?谢谢。

编辑:这是我期望得到的结果:

4
4
4
4
4
4
4

你期望的输出是什么?这似乎按照预期运行。 - Travis Smith
1
你应该尝试使用带有自定义分隔符的CSV模块。CSV.read("path-to-file.csv", col_sep: "\t") - Dmitry Z.
我很难理解这个问题。你说“尝试拆分这个制表符分隔的数据集”,但你没有说你要拆分什么。此外,我无法将“\t\n组合似乎刮掉了最后一个\t”与标题“...在"\t"上拆分会丢失"\n"”调和起来。你是不是想先按换行符拆分,然后在每个字符串上拆分制表符,对于前三行的结果数组以空字符串结尾?如果你能编辑问题并展示你想要的结果,那将非常有帮助。 - Cary Swoveland
此外,我注意到前三行中每个制表符和换行符之间都有一个或多个空格。这是有意为之吗?如果是的话,您想保留这些空格吗? - Cary Swoveland
前三个条目,\t\n 是重要的,并且应该作为 nil 导入记录的数组中,而不是一个由3个成员组成的数组。 - Rich_F
请问您能否编辑一下,以展示您所期望的结果? - Cary Swoveland
1个回答

7
如果这是用于生产环境,你应该使用DmitryZ在评论中提到的CSV类。 CSV处理具有令人惊讶的许多注意事项,因此不应手动操作。

但我们可以将其作为练习进行...


问题在于split方法不会保留分隔符,也不会保留末尾的空列。你遇到了这两个问题。
当你运行 a = text.split(/\n/) 时,a 的元素将不包含换行符。
a = [
    171\t1000\t21\t   
    269\t1000\t25\t   
    389\t1000\t40\t
    1020\t1-03\t30\t1
    1058\t1-03\t30\t1
    1074\t1-03\t30\t1
    200\t300\t\t500
]

然后,如String#split文档所述,"如果省略了limit参数,则会抑制尾随的空字段。",因此,u = i.split(/\t/)将忽略最后一个字段,除非您给它一个限制。

如果您知道它总是4个字段,您可以使用4。

u = i.split(/\t/, 4)

但是使用-1可能更加灵活,因为“如果[限制]为负数,则返回的字段数量没有限制,并且不会抑制尾随的空字段。”这将保留空字段而不需要在CSV中硬编码列数。

u = i.split(/\t/, -1)

我先使用 /\n/ 进行分割。问题在这些部分都显现出来了。那个限制似乎是我一直在寻找的技巧。负限制会扩展所有明显的项目。 - Rich_F

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接