2010-07-02 4 views
-1

.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 

더 좋은 방법이 있다면 알려주세요. 나는 거의 여기에서 땜질하고있다. (그리고 이것은 실제로 내가 해왔 던 첫 번째 루비이다. 당신이 볼 수 있듯이 (그리고 내 정규 표현식 기술은 실제로 닌자 레벨이 아니 었습니다.) 저는 첫 번째 콜론과 그 이후의 모든 것을 제거하려고합니다. Svnversion은 "64:67M"과 같은 것을 반환하며 첫 번째 숫자에만 관심이 있습니다.

은 그 때 나는 같은 파일을 태그 :

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

는 물론, 이러한 비트를 둘러싼 많은 코드가있다. 이것은 무슨 일이 벌어지고있는 것일뿐입니다. 기본적으로 get_version을 호출하여 도우미 객체에 버전 번호를 저장하고 나중에 해당 객체를 AssemblyInfo.cs 파일을 "내용"으로 읽은 다음 대체를 수행하여 다시 작성하는 메서드에서 사용합니다.

모든 출력에서 ​​팬텀 줄 바꿈을 제외하고 잘 작동한다 : 나는 행운에 \ n과 \ r을 필터링합니다 다른 .gsub를 추가하려고했습니다

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

, 나는 시도했다 .chomp, 등등. 항상 결과 파일에 새줄을 넣는 것처럼 보입니다.

나는 분명한 뭔가를 놓치고 있습니까?

[편집 제 않음에 응답하여 :]

여기 AssemblyInfo.cs 파일 편집있어서 puts 라인 AssemblyVersion("1.1.0.62") 출력하지만, 결과 파일 AssemblyVersion("1.1.0.>")

를 도시

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 

+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- 또한 오래된 학교에 다니고 인쇄 문구를 계속 사용할 수 있습니다 (사실, 학교에서 아직도 가르치고있는 내용입니다). 그런 경우 puts 문을 여러 번 반복하면 어떻게됩니까? 또는 p 내용을 gsub 전후에? –

+0

이유가 무엇이든, 오늘 아침에 작동합니다. 내가 포함 파일을 편집 한 후에도 rake 명령에서 동일한 결과를 반환하는 내 Windows 명령 프롬프트에서 이상한 캐싱이 발생했는지 궁금합니다. 오 잘, 어느 쪽의 방법이라도 지금 일한다. 도와 주셔서 감사합니다! – David

답변

1

Readlines는 줄 끝에서 줄 바꿈을 암시 적으로 제거하지 않습니다. 보통 사람들은 chomp를 호출합니다! 그 결과. 당신은 g 메서드를 호출하기 전에 p line을 추가하는 p 메서드 (또는 디버거, 아마도)를 사용하여 이와 같은 것을 파악할 수 있습니다. 그럼 당신은 (내가 놀랍게도 틀림없이) 당신의 버전이 실제로는 "64:67M\n"처럼 보일 것입니다. 그러나 더 쉬운 해결책이 있습니다. String#to_i은 문자열을 정수로 변환하여 숫자가 아닌 것을 찾습니다. 따라서 "64:67M".to_i # => 64"64:67M\n".to_i # => 64은 정규 표현식의 닌자가되는 것을 방지하고 개행 문제를 해결합니다.

+0

이것은 흥미 롭습니다. 디버그 출력을보기 위해 일부 p 명령을 입력하면 올바른 번호가 표시되지만 파일 출력은 새로운 방식으로 손상됩니다. 예를 들어, 다음과 같이 말하면 : AssemblyVersion (\ "# {helper.build_info.build_number_template} \") "을 어셈블리 파일의 my .gsub 바로 앞에두고 올바른 출력을 표시합니다. 그러나 작성된 파일에는 버전 번호가 "1.1.0.>"로 표시됩니다. 이 텍스트 상자는 이것을 보여주기에 충분하지 않습니다. 질문을 수정합니다 ... – David

1

이것은 실제로 당신의 문제를 해결하지 못합니다. 여기에 관용적 인 루비처럼 보이게 만드는 두 번째 방법의 리팩터링이 있습니다. 나는 언어를 배울 때와 같은 방법으로 썼다는 것을 알았지 만, 그 기능을 루비로 작성된 C# 또는 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 

루비 코드에는 개인적인 스타일이 많이 포함되어 있습니다. 이런 종류의 일은 내가 배우고있을 때 나에게 순수한 금 이었기 때문에 나는 내가 변화시킨 것을 왜 바꿨는지에 대해 단계적으로 자세히 살펴볼 것입니다.

그래서, 상단에서 시작 :

는 먼저 나는 메소드 서명에서 괄호 떨어졌다. 일반적으로, 지나치게 구두점을 쓰면 읽을 수 없으므로 필요하지 않으면 괄호를 사용하지 않아야합니다. 또한 file_path에서 경로로 이동했습니다. 다시 말하지만, 이것은 단순한 것 (개인 취향)입니다.

다음으로는 항상 unless이 사용됩니다. 조금 익숙해 지지만, 읽는 동안해야 할 불리한 대수학이 적을수록 좋습니다. 일부 괄호도 제거 (처음과 동일한 추론)하고 ||or으로 전환했습니다.

and/or&&/||에 관해서는, 전 (구두점의 요점으로 돌아가는) 꽤 많이 좋아합니다. 즉, 연산자 우선 순위의 차이로 인해 해당 양식을 사용하여 발생할 수있는 상당히 큰 문제가 있습니다. 먼저 무슨 일이 일어날 지이

def foo bar 
    'foobar!' if bar 
end 

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

같은 뭔가를 말할 수 것은 truefalse || true 의지를 평가하고, 다음 truefoo에 전달됩니다. 우리가

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

먼저 다른 길을 갈 경우, falsefoo에 전달 얻을 것이다. foonil을 반환하고 nil은 부울 식으로 false으로 간주되므로 nil or truetrue으로 평가됩니다.

여기서 알 수 있듯이, 이것은 정말로 이상한 버그가 될 수 있습니다. 그 때문에 많은 루비스트들이 단지 & &/||을 사용합니다. 독점적으로 양식. 개인적으로, 나는 그 문제를 마음 속에 지키려고 노력한다. 왜냐하면 나는 정말로 좋아하고 그리고/또는 더 좋기 때문이다.

가드 절 마지막 점 %{...} 구문의 따옴표를 바꿨습니다. 루비에서 문자열 리터럴을 만드는 방법은 완전히 미친 양입니다. 그렇기 때문에 따옴표에서 벗어나야하는 것을 피할 수있는 방법이 항상 있습니다.

다음 변경 사항은 간결한 이름으로 변경되었습니다. 일반적인 방법으로, 나는 스타일 변수이기는하지만 사용하는 변수의 양을 최소화하려고합니다.

다음 변경이 가장 큽니다.

내가했던 첫 번째 작업은 우리가 동일하게 유지하기를 원했던 시작과 끝 비트 주위에 그룹화 (())를 가지고 모든 정규 표현식을 변경하고 변경하려는 항목 주위의 그룹화를 제거했습니다. gsub을 사용하면 다른 쪽 그룹의 일치 항목 (\1은 첫 번째 그룹 인 \2 초)을 참조 할 수 있기 때문에 그렇게했습니다. 잡음을 줄이는 데 많은 도움이됩니다. 정규 표현식은 이미 읽기가 어렵습니다 .-)

다음은 기본적으로 똑같은 연산을 무차별 방식으로 네 가지에 적용하는 것입니다. 자신이 그렇게하는 것을 발견하면 일반적으로 작업을 원하는 작업과 분리하면 훨씬 더 명확 해집니다. 여기서 또 다른 고려 사항은 우리가 온건하게 긴 정규 표현식을 다루고 있다는 것이며, 다시 한번, 모든 것을 독자적으로 읽을만큼 어렵다는 것입니다.

정규식의 해시에 해당 항목을 가져오고이를 대체 할 항목을 훨씬 명확하게 만듭니다. 이제 해시를 반복하고 대치 할 수 있습니다.

내가 gsubgsub!으로 변경하고 할당을 제거한 것을 볼 수 있습니다. 일반적으로 !으로 끝나는 메소드는 !으로 끝나지 않는 메소드의 변종이 될 수 있지만 사용 방법에주의를 기울여야합니다. 이 경우 gsub은 대체 문자열을 사용하여 새 문자열을 반환하고 gsub!은 대체 문자열을 대체합니다. 또 다른 요점은 루비에서는 문자열이 변경 가능하다는 점입니다. 이것은 C#과 미묘한 차이가 있지만 장소 대체와 같은 것을 허용합니다.

일반적으로 대부분의 차이점은 세 가지로 요약 할 수 있습니다. DRY (반복하지 말 것)는 루비에서 더 이상 취해지지 않는다. C#에서는 구두점을 사용할 필요가 없다면 사용하지 말고 최소한의 타이핑만으로도 언어의 간결함을 포용하지 말라. (가독성을 떨어 뜨리기 전에)

: 당신의 갱신에 관해서

+0

이것은 내 일반적인 루비 프로그래밍에 매우 도움이되었습니다. 감사합니다. 이것은 루비에서의 첫 번째 시도이기 때문에 티가 확실히 C# 프로그래머가 작성한 것처럼 보일 것입니다 :)하지만 분명히 "같은 것을하기위한 다른 구문"이 아니라 오히려 "다른 방식으로 사용하려고합니다. 일을하는거야. " 언어에는 많은 고유 한 장점이 있으며 문제를 다르게 접근하기 위해 시간을 투자해야합니다. 감사! – David

관련 문제