2013-05-08 35 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