2010-07-02 179 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