2009-03-28 1 views
1

Ruby의 Ruby 앱에서 파서를 작성하여 문자열에서 일부 메타 데이터를 추출하려고합니다. ruby의 문자열에서 마지막 괄호 세트 사이의 부분 문자열을 구문 분석하는 방법

은의 샘플 문자열이 있다고 가정 해 봅시다 :

는 빠른 붉은 여우 (프랭크, 10)는 게으른 갈색 강아지 (랄프, 20)를 통해 증가했다.

()의 마지막 부분에서 부분 문자열을 추출하고 싶습니다.

그래서 문자열에 얼마나 많은()이 있더라도 "ralph, 20"을 얻고 싶습니다.

이 루비 문자열 추출을 만드는 가장 좋은 방법은 ... regexp가 있습니까?

감사합니다,

답변

1

나는 (따라 조정, 여기 내 정규식 첫 번째 값이 숫자이고 두 번째 값이 숫자라고 가정)이 시도됩니다. 다음은 스캔 배열로 모든 항목을 가져오고 -1 당신이 요구하는지 그냥 뭐 것 같다 단지 마지막, 잡아 우리에게 알려줍니다 : 당신이 sexeger을 원하는 것 같습니다

>> foo = "The quick red fox (frank,10) jumped over the lazy brown dog (ralph, 20)." 
=> "The quick red fox (frank,10) jumped over the lazy brown dog (ralph, 20)." 
>> foo.scan(/\(\w+, ?\d+\)/)[-1] 
=> "(ralph, 20)" 
+0

신난다! ... 나는 그것을 foo.scan (/\(.*,*.*\)/)[- 1]로 바 꾸었습니다. 왜냐하면 실제로 그것을 예제 문자 유형으로 제한 할 필요가 없기 때문입니다. 감사합니다 – Streamline

+0

s.scan (/\(.*?\)/)[-1]; 더 쉬워? –

+0

또는 욕심이없는 성냥이 마음에 들지 않으면 s.scan (/ \ ([^]) * \) /) [- 1]. –

2

합니다. 그들은 문자열을 역전시키고 문자열에 대해 역 정규식을 실행 한 다음 결과를 반대로 작업합니다.

#!/usr/bin/ruby 

s = "The quick red fox (frank,10) jumped over the lazy brown dog (ralph, 20)."; 

reversed_s = s.reverse; 
reversed_s =~ /^.*?\)(.*?)\(/; 
result = $1.reverse; 
puts result; 

이 더까지 투표를 받고되지 않는다는 사실은 나를 아무도 당신이 sexeger를 사용하려는 이유 읽기를 통해 클릭하지 알 수 있으므로, 예를 들면 다음과 같습니다 (난 정말 루비를 모르는 코드를 용서)입니다 여기

do they all return the same thing? 
ralph, 20 
ralph, 20 
ralph, 20 
ralph, 20 
         user  system  total  real 
scan greedy   0.760000 0.000000 0.760000 ( 0.772793) 
scan non greedy  0.750000 0.010000 0.760000 ( 0.760855) 
right index   0.760000 0.000000 0.760000 ( 0.770573) 
sexeger non greedy 0.400000 0.000000 0.400000 ( 0.408110) 

그리고 벤치 마크 :

#!/usr/bin/ruby 

require 'benchmark' 

def scan_greedy(s) 
    result = s.scan(/\([^)]*\)/x)[-1] 
    result[1 .. result.length - 2] 
end 

def scan_non_greedy(s) 
    result = s.scan(/\(.*?\)/)[-1] 
    result[1 .. result.length - 2] 
end 

def right_index(s) 
    s[s.rindex('(') + 1 .. s.rindex(')') -1] 
end 

def sexeger_non_greedy(s) 
    s.reverse =~ /^.*?\)(.*?)\(/ 
    $1.reverse 
end 

s = "The quick red fox (frank,10) jumped over the lazy brown dog (ralph, 20)."; 

puts "do they all return the same thing?", 
    scan_greedy(s), scan_non_greedy(s), right_index(s), sexeger_non_greedy(s) 

n = 100_000 
Benchmark.bm(18) do |x| 
    x.report("scan greedy")  { n.times do; scan_greedy(s); end } 
    x.report("scan non greedy") { n.times do; scan_non_greedy(s); end } 
    x.report("right index")  { n.times do; scan_greedy(s); end } 
    x.report("sexeger non greedy") { n.times do; sexeger_non_greedy(s); end } 
end 
+0

흥미 롭고 (철저히!) ... 응답에 도달하는 데 걸리는 시간의 속도를 나타내는 벤치 마크입니까? – Streamline

+0

예, 구체적으로 함수를 100,000 번 실행하는 시간입니다. 인상적인 차이를보고 싶다면 s를 "(foo) (foo) (foo) (foo) (bar)"로 변경하고 n을 10000으로 변경하십시오. –

1

간단한 비 정규 표현식 솔루션 :

여기있는 벤치 마크의 결과는 16,
string = "The quick red fox (frank,10) jumped over the lazy brown dog (ralph, 20)." 
string[string.rindex('(')..string.rindex(')')] 

예 : 괄호없이

irb(main):001:0> string = "The quick red fox (frank,10) jumped over the lazy brown dog (ralph, 20)." 
=> "The quick red fox (frank,10) jumped over the lazy brown dog (ralph, 20)." 
irb(main):002:0> string[string.rindex('(')..string.rindex(')')] 
=> "(ralph, 20)" 

그리고 :

irb(main):007:0> string[string.rindex('(')+1..string.rindex(')')-1] 
=> "ralph, 20" 
관련 문제