这就是我想要做的,但如果可能的话,使用单线程:
lines = Array.new
File.open('test.txt').each { |line| lines << line }
Run Code Online (Sandbox Code Playgroud)
可能?
我有一个约150mb的简单文本文件.我的代码将读取每一行,如果它匹配某些正则表达式,它将被写入输出文件.但是现在,只需要很长时间来遍历文件的所有行(几分钟)就可以了
File.open(filename).each do |line|
# do some stuff
end
Run Code Online (Sandbox Code Playgroud)
我知道这是循环文件的线路需要一段时间,因为即使我对"#do some stuff"中的数据什么都不做,它仍然需要很长时间.
我知道有些unix程序几乎可以立即解析像这样的大文件(比如grep),所以我想知道为什么ruby(MRI 1.9)需要这么长时间才能读取文件,有没有办法让它更快?
我想逐行处理文件。但是,这些文件具有不同的行分隔符:"\r","\n"或"\r\n". 我不知道他们使用的是哪种操作系统,也不知道他们来自哪种操作系统。
我有两个解决方案:
使用 bash 命令将这些分隔符转换为"\n".
cat file |
tr '\r\n' '\n' |
tr '\r' '\n' |
ruby process.rb
Run Code Online (Sandbox Code Playgroud)读取整个文件并 gsub 这些分隔符
text=File.open('xxx.txt').read
text.gsub!(/\r\n?/, "\n")
text.each_line do |line|
do some thing
end
Run Code Online (Sandbox Code Playgroud)但是当文件很大时,第二种解决方案并不好。见参考。有没有其他 ruby 惯用且有效的解决方案?
我试图解析一个文本文件,每行包含可变数量的单词和数字,如下所示:
foo 4.500 bar 3.00
1.3 3 foo bar
Run Code Online (Sandbox Code Playgroud)
如何读取由空格而不是换行符分隔的文件?有没有什么方法可以设置File("file.txt").foreach方法使用空格而不是换行符作为分隔符?
我不确定这个问题只与ruby有关,也许你会发现它与任何其他语言相关.
我想知道我是否应该使用解析或foreach:
CSV.parse(filepath)将解析整个文件并返回一个数组数组,这些数组将反映csv文件并将存储在内存中.稍后,我将处理此数组行.
CSV.foreach(filepath) 将逐行读取/解析文件并逐行处理.
谈到性能,有什么区别吗?有一个更好的方法吗?
PS:我知道在ruby中我可以使用parse方法提供一个块然后它将分别处理每一行.
我有一个这样的输入文件:
This is a text block start
This is the end
And this is another
with more than one line
and another line.
Run Code Online (Sandbox Code Playgroud)
所需的任务是按由某些特殊行分隔的部分读取文件,在本例中它是一个空行,例如 [out]:
[['This is a text block start', 'This is the end'],
['And this is another','with more than one line', 'and another line.']]
Run Code Online (Sandbox Code Playgroud)
我通过这样做得到了所需的输出:
def per_section(it):
""" Read a file and yield sections using empty line as delimiter """
section = []
for line in it:
if line.strip('\n'):
section.append(line)
else:
yield ''.join(section)
section = []
# yield …Run Code Online (Sandbox Code Playgroud) 有没有办法使用mapRuby 中的方法编辑 CSV 文件?我知道我可以使用以下方法打开文件:
CSV.open("file.csv", "a+")
Run Code Online (Sandbox Code Playgroud)
并向其添加内容,但我必须编辑一些特定的行。
该foreach方法仅对读取文件有用(如果我错了,请纠正我)。
我检查了 Ruby CSV 文档,但找不到任何有用的信息。
我的 CSV 文件少于 1500 行,所以我不介意阅读所有行。
我有一个如下所示的数据文件:
Things
??? Foo
? ??? 1. Item One
? ??? 2. Item Two
? ??? 3. Item Three
? ??? 4. Item Four
? ??? 5. Item Five
? ??? 6. Item Six
??? Bar
? ??? 1. Item Seven
? ??? 2. Item Eight
? ??? 3. Item Nine
Run Code Online (Sandbox Code Playgroud)
我要做的是找到一个字符串,与之关联的数字,以及作为('Foo'或'Bar')一部分的子标题
抓取项目和数字很容易:
str = "Item One"
data.each_line do |line|
if line =~ /#{str}/
/(?<num>\d).\s(?<item>.*)/ =~ line
end
end
Run Code Online (Sandbox Code Playgroud)
但我不确定如何获得副标题.我的想法是,一旦我找到了这条线,我可以使用这个数字从那一点算起来.是否有readlines或seek命令或其他一些可以执行此操作的命令?
感谢帮助!
我有一个大小约10 GB的字符串(大量的RAM使用...).问题是,我需要执行像gsub和split这样的字符串操作.我注意到Ruby会在某个时刻"停止工作"(尽管没有产生任何错误).
例:
str = HUGE_STRING_10_GB
# I will try to split the string using .split:
str.split("\r\n")
# but Ruby will instead just return an array with
# the full unsplitted string itself...
# let's break this down:
# each of those attempts doesn't cause problems and
# returns arrays with thousands or even millions of items (lines)
str[0..999].split("\r\n")
str[0..999_999].split("\r\n")
str[0..999_999_999].split("\r\n")
# starting from here, problems will occur
str[0..1_999_999_999].split("\r\n")
Run Code Online (Sandbox Code Playgroud)
我正在使用Ruby MRI 1.8.7,这里有什么问题?为什么Ruby无法对巨大的字符串执行字符串操作?什么是解决方案?
我想出的唯一解决方案是使用[0..9],[10..19],"循环"字符串,并逐个执行字符串操作.然而,这似乎是不可靠的,例如,如果我的拆分分隔符非常长并且落在两个"部分"之间.
实际上工作正常的另一个解决方案是像str.each_line {..}一样迭代字符串.但是,这只是替换了换行符分隔符.
编辑:谢谢你的所有答案.就我而言,"巨大的10 GB STRING"实际上是从互联网上下载的.它包含由特定序列分隔的数据(在大多数情况下是简单的换行符).在我的场景中,我将10 GB文件的EACH ELEMENT与我脚本中已有的另一个(较小的)数据集进行比较.我感谢所有的建议.
该字符串源自以下内容的返回值:
> msg = imap.uid_fetch(uid, ["RFC822"])[0].attr["RFC822"]
Run Code Online (Sandbox Code Playgroud)
在控制台中,如果我键入msg,则会显示一个带有双引号的长字符串,并且\ r \n分隔每行:
> msg
"Delivered-To: email@test.com\r\nReceived: by xx.xx.xx.xx with SMTP id;\r\n"
Run Code Online (Sandbox Code Playgroud)
如果我将其中一部分与正则表达式匹配,则返回值为\ r \n:
> msg[/Delivered-To:.*?\s+Received:/i]
=> "Delivered-To: email@test.com\r\nReceived:"
Run Code Online (Sandbox Code Playgroud)
如果我将字符串保存到文件中,请将其读回并与相同的正则表达式匹配,我得到\n而不是\ r \n:
> File.write('test.txt', msg)
> str = File.read('test.txt')
> str[/Delivered-To:.*?\s+Received:/i]
=> "Delivered-To: email@test.com\nReceived:"
Run Code Online (Sandbox Code Playgroud)
当字符串保存到文件时,\ r \n是否转换为\n?有没有办法将字符串保存到文件中,在没有修改行结尾的情况下将其读回?
我想用新行替换文件中的一行,例如:
文件:
test
test
test
testing
test
Run Code Online (Sandbox Code Playgroud)
来源:
def remove_line(line)
if line == line
#remove line including whitespace
File.open('test.txt', 'a+') { |s| s.puts('removed successfully') }
end
end
Run Code Online (Sandbox Code Playgroud)
因此,预期的输出将是这样的:
remove_line('testing')
test
test
test
removed successfully
test
Run Code Online (Sandbox Code Playgroud)
现在我做了一些研究,只能找到添加一个空行,我想我可以运行它并删除所有空行,然后附加到文件中,但必须有一种更简单的方法来替换行用另一个字符串?
我试图找到以相反顺序处理Ruby字符串中的行的最有效方法.这是我的两种方法:
def double_reverse(lines)
lines.reverse!
lines.each_line do |line|
line.chomp!
line.reverse!
puts line
end
end
def split_and_reverse(lines)
lines.split("\n").reverse.each do |line|
puts line
end
end
if __FILE__ == $0
lines = "This is the first line.\nThis is the second line"
double_reverse(lines)
lines = "This is the first line.\nThis is the second line"
split_and_reverse(lines)
end
Run Code Online (Sandbox Code Playgroud)
我想知道哪一个会使用更少的内存.还有其他方法可以使用更少的资源吗?我主要关心的是内存使用情况,但是如果我可以减少CPU的使用率也会很好.
编辑1:
在我的用例中lines可以有超过一百万行.如果split要将内存使用量增加2倍,那对我来说肯定是个问题.但是,如果Ruby VM足够聪明,可以确定lines在调用split并释放内存之后不会使用它,那么这可能不是问题.另一方面,就地reverse!方法在理论上似乎更有效,因为它可以在不做任何副本的情况下完成lines.