2010-07-02 95 views
-1

我正在使用rake腳本標記我的.NET項目中的AssemblyInfo.cs文件,但是有一個虛幻回車符(或換行符等)被引入,這會破壞編譯。獲取版本號的方法是:這個換行符來自哪裏?

def get_version() 
    version = '' 
    IO.popen("#{SVNVERSION_APPLICATION} #{build_info.root_dir}") do |output| 
    output.readlines.each do |line| 
     version << line.gsub(/\:.*/, '') 
    end 
    end 
    result = version 
end 

如果有更好的方法可以做到這一點,請告訴我。我在這裏大部分都是修補(這實際上是我工作過的第一個Ruby,所以請耐心等待)。正如你所看到的(我的正則表達式技能從來不是真正的忍者級別),我只是試圖擺脫第一個冒號和後面的所有內容。 Svnversion返回諸如「64:67M」之類的內容,我只對第一個數字感興趣。

然後我標記文件這樣:

contents = contents.gsub(/AssemblyVersion\(\"([\d.*]*)\"\)/, "AssemblyVersion(\"#{helper.build_info.build_number_template}\")") 

當然,還有周圍的這些位更多的代碼。這只是發生了什麼事情的肉。基本上,在我調用get_version的任務中,將版本號存儲在助手對象上,該對象稍後用於將AssemblyInfo.cs文件讀入「內容」並執行替換並將其寫回的方法。

一切工作正常,除了在輸出幻像換行符:

[assembly: AssemblyVersion("1.1.0.62 
")] 
[assembly: AssemblyFileVersion("1.1.0.62 
")] 

我已經嘗試添加另一個.gsub設法過濾掉\ n和\ r沒有運氣,我已經試過.chomp等。它似乎總是把這個換行符放在結果文件中。

我失去了一些東西明顯?

[編輯響應於第一個答案:]

下面是編輯AssemblyInfo.cs文件的方法,包括:

def replace_assembly_strings(file_path, helper) 

    if not (File.exists?(file_path) || File.writable?(file_path)) 
     raise "the file_path \"#{file_path}\" can not be written to. Does it exist?" 
    end 

    path = Pathname.new(file_path) 
    contents = path.read 
    puts "AssemblyVersion(\"#{helper.build_info.build_number_template}\")" 
    contents = contents.gsub(/AssemblyVersion\(\"([\d.*]*)\"\)/, "AssemblyVersion(\"#{helper.build_info.build_number_template}\")") 
    contents = contents.gsub(/AssemblyFileVersion\(\"([\d.*]*)\"\)/, "AssemblyFileVersion(\"#{helper.build_info.build_number_template}\")") 
    contents = contents.gsub(/AssemblyCompany\(\"(.*)\"\)/, "AssemblyCompany(\"#{helper.build_info.company}\")") 
    contents = contents.gsub(/AssemblyCopyright\(\"(.*)\"\)/, "AssemblyCopyright(\"#{helper.build_info.copyright}\")") 

    File.open(file_path, 'w') {|f| f.write(contents)} 

    end 

puts線輸出AssemblyVersion("1.1.0.62")但生成的文件顯示AssemblyVersion("1.1.0.>")

+1

在問候你的更新,它看起來像'helper.build_info.build_number_template'是給你不同的結果第一第二次你打電話給它。您可能有興趣嘗試調試此代碼。這裏是一個關於設置和使用調試器的鏈接http://pivotallabs.com/users/chad/blog/articles/366-ruby-debug-in-30-seconds-we-don-t-need-no- stinkin-gui-你也可以去舊學校,並繼續使用打印語句(實際上,這是他們在我的學校仍然教授的內容)在這種情況下,如果你多次重複你的語句,會發生什麼?或者在gsub之前和​​之後的p內容? – 2010-07-03 06:12:57

+0

無論出於何種原因,它今天早上都有效。我想知道是否在我的Windows命令提示符上發生了一些奇怪的緩存,即使在編輯包含文件後,它也會從rake命令返回相同的結果。哦,無論哪種方式現在它的作品。謝謝您的幫助! – David 2010-07-06 12:06:12

回答

1

Readlines不會隱含地從行尾刪除換行符。通常人們會調用chomp!結果。你可以用p方法(或者調試器,我想)來計算這樣的事情,在調用gsub之前添加p line。那麼你應該看到(除非我是錯誤的)你的版本看起來像"64:67M\n"然而,你有一個更簡單的解決方案,String#to_i將字符串轉換爲int,直到它找到一個非數字。所以"64:67M".to_i # => 64"64:67M\n".to_i # => 64它可以讓你不必成爲一個正則表達式忍者,並解決你的換行問題。

+0

這很有趣。放入一些p命令來查看調試輸出會顯示正確的編號,但文件輸出現在以新的方式被破壞。例如,如果我在彙編文件的.gsub之前說:puts「AssemblyVersion(\」#{helper.build_info.build_number_template} \「)」,它會顯示正確的輸出。但是在寫入的文件中,它將版本號顯示爲「1.1.0。>」。這個文本框不夠漂亮,我將編輯這個問題...... – David 2010-07-02 18:45:50

1

這並不能真正解決您的問題,這裏有一點是對第二種方法的重構,使它看起來更像是慣用的ruby。我知道我在學習語言的時候以同樣的方式寫了它,但是有很多東西使得這個函數看起來像C#或用ruby編寫的java。

def replace_assembly_strings path, helper 
    raise %{the path "#{path}" can not be written to. Does it exist?} unless File.exists?(path) or File.writable?(path) 

    file = Pathname.new(path).read 

    methods = {/(AssemblyVersion\(\")[\d.*]*(\"\))/  => helper.build_info.build_number_template, 
      /(AssemblyFileVersion\(\")[\d.*]*(\"\))/ => helper.build_info.build_number_template, 
      /(AssemblyCopyright\(\").*(\"\))/   => helper.build_info.copyright, 
      /(AssemblyCompany\(\").*(\"\))/   => helper.build_info.company} 

    methods.keys.each do |regex| 
    file.gsub! regex, "\1#{methods[regex]}\2" 
    end 

    File.open(path, 'w') {|f| f.write(file)} 
end 

ruby​​代碼中涉及很多個人風格,這只是我會這樣做的方式。當我學習時,這種事情對我來說是純金,所以我會一步一步詳細解釋爲什麼我改變了我改變的東西。

所以,從頂部開始:)

首先我是從方法簽名放棄了括號。作爲一種慣例,除非你需要,否則你不應該使用parens,因爲過多的標點符號會使東西難以閱讀。也從file_path到path,再次,這只是一個簡單的事情(和個人的品味)

接下來,你永遠不會看到if not紅寶石,unless總是使用。它需要一些習慣,但在閱讀時需要做的布爾代數越少越好。同樣刪除了一些parens(與第一次相同),並將||更改爲or

說到and/or vs &&/||,我喜歡前者多一點(回到標點符號上)。話雖如此,但由於運算符優先級的差異,使用該表單可能會出現相當大的問題。比方說,你有這樣的事情

def foo bar 
    'foobar!' if bar 
end 

foobar = foo false || true 
# foobar == 'foobar!' 

會發生第一件事就是false || true意志評價true,然後true被傳遞到foo。如果我們走另一條路

foobar = foo false or true 
# foobar == true ???? 

第一,false將得到傳遞給foofoo將返回nil,nil被認爲是false布爾表達式,因此nil or true結束了評估到true

正如你所看到的,這可能會導致真正奇怪的錯誤。正因爲如此,很多紅寶石主義者只是使用了這種方法。完全形式。就我個人而言,我只是想記住這個問題,因爲我非常喜歡和/或更好。

守衛子句的最後一點,我換了%{...}語法的引號。在ruby中使用字符串文字有絕對瘋狂的數量。因此,總是有一種方法可以避免不必要的引號。

接下來的變化只是在簡潔的名義。一般來說,我儘量減少我使用的變量的數量,儘管這也是一種風格。

下一個變化是最大的。

我做的第一件事就是改變你所有的正則表達式,在我們想要保持相同的開始和結束位周圍有一個分組(()),並且移除圍繞我們想要改變的東西的分組。我這樣做是因爲使用gsub,我們可以得到任何與對方組匹配的參考(\1是第一組,\2第二組)。這對減少噪音有很大幫助,正則表達式已經足夠難以閱讀;-)

接下來,我試圖解決你基本上以暴力方式將相同的操作應用於四件事情。當你發現自己這樣做時,如果將操作與操作分開,它通常會使事情變得更加清晰。這裏的另一個考慮是我們正在處理中等長度的正則表達式,這些正則表達式又很難自行讀取。

將這些東西放到正則表達式的散列表中,以及用什麼來替換它,使得更清晰。所以現在我們可以遍歷該散列並進行替換。

您可能會注意到我將gsub更改爲gsub!,並刪除了該作業。一般而言,以!結尾的方法將是不以!結尾的方法的變體,但在某種方式下,您必須更加註意使用它。在這種情況下,gsub返回帶有替換的新字符串,gsub!進行替換。還有一點需要注意的是,在ruby中,字符串是可變的,這對C#來說是一個微妙的區別,但它允許替換等。

一般來說,大部分的差異可以歸結爲三件事情; DRY(不要重複自己)在ruby中被進一步採用,然後在C#中使用,除非需要,否則不要使用標點符號,並且通過儘可能少地鍵入內容來實現語言的簡潔性(在降低可讀性之前)

讓我知道如果您有任何意見/問題,祝你好運與您的進一步紅寶石冒險:)

+0

這對我的一般Ruby編程非常有幫助,謝謝。這實際上是我第一次嘗試Ruby,因此Ti看起來像是由C#程序員編寫的:)但我絕對想要將它看作不是「用不同的語法來做同樣的事情」,而是「以不同的方式做事情。「語言有很多固有的優勢,我必須花時間以不同的方式解決問題。謝謝! – David 2010-07-06 12:05:01