我有一个包含许多代码的文件,我想将它们全部重构到自己的文件中。有问题的文件有大约 30k 行,所以我不想手动操作。
每个部分开始:
module MyModule
(我改了这个名字)
是否有按标记拆分文件的功能?当我使用时,File.readlines
我找不到分割数组的好方法。
我不在乎你怎么想给他们起名字。
我重构了你的代码。
File.read('lib/odin.rb').split(/module Odin/).each do |mod|
File.open("#{mod[/class (\w+)/, 1]}.rb", "w") do |f|
f.write("module Odin")
f.write(mod)
end
end
我找到了答案,详细写下问题。
我将其作为答案发布,但我会将答案奖励给其他有更好解决方案的人:
big_file = File.readlines 'lib/odin.rb'
big_file.
join(' ').
split(/module Odin/).
map!{|w| w.prepend("module Odin\n") }.
each do |f|
name = "#{f.match(/class ([a-zA-Z]+)/)[1].underscore}.rb"
File.open(name, "w") do |n|
n.write(f)
end
end
我还想到了一种根据内容命名输出文件的好方法;但我不在乎你会如何命名它们。
Ruby 有一个很棒的方法,它是 Enumerable 的一部分,称为slice_before
:
require 'pp'
modules = DATA.readlines.map(&:chomp).slice_before(/^module MyModule/).map{ |a| a.join("\n") }
pp modules
__END__
module MyModule
# 1 stuff
end
module MyModule
# 2 stuff
end
module MyModule
# 3 stuff
end
这是显示内容的输出modules
:
["模块 MyModule\n #1 东西\nend\n", "module MyModule\n # 2 stuff\nend\n", "module MyModule\n # 3 stuff\nend"]
DATA
是继承自 Perl 的 Ruby 的花招。之后源文件中的所有内容都__END__
被视为“数据”块的一部分,解释器在DATA
文件句柄中将其提供给正在运行的代码,并且就像数据文件一样。这意味着我们可以在其上使用 IO 方法,例如readlines
,类似于我们使用IO.readlines
. 我在这里使用__END__
andDATA
是因为它们便于简单的测试和简短的脚本。
readlines
读取行时不会删除尾随行尾,这就是这样map(&:chomp)
做的。DATA.read.split("\n")
会完成同样的事情。
slice_before
是使这项工作发挥作用的魔力。它需要一个数组并遍历它,创建每次模式找到命中时开始的子数组。之后,这只是在写入文件之前将子数组的内容重新加入单个字符串的情况。
之后,您只需要循环modules
,将每个文件保存到不同的文件中:
modules.each.with_index(1) do |m, i|
File.write("module_#{ i }.rb", m)
end
with_index
是 Enumerator 中一个不错的小方法,当我们需要知道我们正在处理的数组中的哪个项目时,它很有用。在这种情况下,它类似于each_with_index
我们可以指定起始偏移值。1