2013-05-08 38 views
0

我有一个包含许多代码的文件,我想将它们全部重构到它们自己的文件中。有问题的文件有大约3万行,所以我不想亲自去做。如何通过grep与红宝石分割文件?

每个部分的开始:

module MyModule 

(我已经改变了这个名字)


是否有分割每个标记文件的功能?当我使用File.readlines时我无法找到拆分数组的好方法。

我不在乎你怎么想他们的名字。

+1

你是什么意思分裂文件?分成新的文件? – squiguy 2013-05-08 23:42:27

+0

@squiguy是的,进入文件 – 2013-05-08 23:44:26

+0

我强烈建议每次你移动一些东西时手工操作并运行规范,这样你就知道每一步都没有破坏任何东西。这将需要更长的时间,但将是坚实的重构。我绝对不会试图自动化 - 我喜欢自动化的东西。 – kikuchiyo 2013-05-08 23:44:30

回答

1

红宝石具有可枚举的部分称为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包含输出:

 
["module MyModule\n # 1 stuff\nend\n", 
"module MyModule\n # 2 stuff\nend\n", 
"module MyModule\n # 3 stuff\nend"] 

DATA是Ruby的花招OF-一手从Perl继承而来。 __END__之后的源文件中的所有内容都被视为“数据”块的一部分,该数据块由DATA文件句柄中的解释器提供给运行代码,并充当数据文件。这意味着我们可以在其上使用IO方法,例如readlines,与我们如何使用IO.readlines类似。我在这里使用__END__DATA,因为它们对于简单测试和简短脚本很方便。

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是枚举一个不错的方法,当我们需要知道这一个项目是有益的我们正在处理的数组。它类似于each_with_index,只是我们可以指定起始偏移值,在这种情况下为1

+0

我给你的答案,因为'slice_before'是我最需要的方法。你还提供了一些有趣的勘误和琐事,教育了我。这个问题本身只是通过'__DATA__'的使用而变得复杂,但我一定会记住这一点。如果你有一个疯狂的使用案例,我很乐意听到它。 – 2013-05-19 17:25:10

+0

当将类似文件的内容存储在磁盘上或在线可用时,“DATA”是一种方便,而不是浪费时间来显示如何创建样本数据文件并参考它。用于'DATA'的用例? Ruby并没有那么用,但是它被用于很多Perl代码。 – 2013-05-19 17:40:45

+1

此链接有助于解释。 Ruby没有'__DATA__',但其余的都是有效的。 http://docstore.mik.ua/orelly/perl/cookbook/ch07_07.htm – 2013-05-19 17:47:47

1

我已经找到了答案,详细写出了问题。

我张贴它作为一个答案,但我会颁发的答案给别人,有一个更好的解决方案:

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 

我又想到了一个很好的方式来命名基于输出文件内容;但我不在乎你如何去想它们的名字。

2

我重构了你的代码。

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 
+0

这样读起来更容易。 – 2013-05-09 00:10:45