我有一個包含許多代碼的文件,我想將它們全部重構到它們自己的文件中。有問題的文件有大約3萬行,所以我不想親自去做。如何通過grep與紅寶石分割文件?
每個部分的開始:
module MyModule
(我已經改變了這個名字)
是否有分割每個標記文件的功能?當我使用File.readlines
時我無法找到拆分數組的好方法。
我不在乎你怎麼想他們的名字。
我有一個包含許多代碼的文件,我想將它們全部重構到它們自己的文件中。有問題的文件有大約3萬行,所以我不想親自去做。如何通過grep與紅寶石分割文件?
每個部分的開始:
module MyModule
(我已經改變了這個名字)
是否有分割每個標記文件的功能?當我使用File.readlines
時我無法找到拆分數組的好方法。
我不在乎你怎麼想他們的名字。
紅寶石具有可枚舉的部分稱爲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
。
我給你的答案,因爲'slice_before'是我最需要的方法。你還提供了一些有趣的勘誤和瑣事,教育了我。這個問題本身只是通過'__DATA__'的使用而變得複雜,但我一定會記住這一點。如果你有一個瘋狂的使用案例,我很樂意聽到它。 – 2013-05-19 17:25:10
當將類似文件的內容存儲在磁盤上或在線可用時,「DATA」是一種方便,而不是浪費時間來顯示如何創建樣本數據文件並參考它。用於'DATA'的用例? Ruby並沒有那麼用,但是它被用於很多Perl代碼。 – 2013-05-19 17:40:45
此鏈接有助於解釋。 Ruby沒有'__DATA__',但其餘的都是有效的。 http://docstore.mik.ua/orelly/perl/cookbook/ch07_07.htm – 2013-05-19 17:47:47
我已經找到了答案,詳細寫出了問題。
我張貼它作爲一個答案,但我會頒發的答案給別人,有一個更好的解決方案:
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
我又想到了一個很好的方式來命名基於輸出文件內容;但我不在乎你如何去想它們的名字。
我重構了你的代碼。
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
這樣讀起來更容易。 – 2013-05-09 00:10:45
你是什麼意思分裂文件?分成新的文件? – squiguy 2013-05-08 23:42:27
@squiguy是的,進入文件 – 2013-05-08 23:44:26
我強烈建議每次你移動一些東西時手工操作並運行規範,這樣你就知道每一步都沒有破壞任何東西。這將需要更長的時間,但將是堅實的重構。我絕對不會試圖自動化 - 我喜歡自動化的東西。 – kikuchiyo 2013-05-08 23:44:30