[ruby] Ruby Regexp 그룹 매칭, 한 줄에 변수 할당

현재 문자열을 여러 변수로 rexp하려고합니다. 예제 문자열 :

ryan_string = "RyanOnRails: This is a test"

이 정규 표현식과 3 개의 그룹을 일치 시켰습니다.

ryan_group = ryan_string.scan(/(^.*)(:)(.*)/i)

이제 각 그룹에 액세스하려면 다음과 같이해야합니다.

ryan_group[0][0] (first group) RyanOnRails
ryan_group[0][1] (second group) :
ryan_group[0][2] (third group) This is a test

이것은 꽤 우스꽝스럽고 내가 뭔가 잘못하고있는 것처럼 느껴집니다. 다음과 같이 할 수있을 것으로 기대합니다.

g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)

이게 가능해? 아니면 내가하는 것보다 더 좋은 방법이 있습니까?



답변

scan말이 안되므로 이것을 원하지 않습니다 . 객체 String#match를 반환하는 것을 사용할 수 있으며 캡처 배열을 반환하도록 MatchData호출 할 수 있습니다 #captures. 이 같은:

#!/usr/bin/env ruby

string = "RyanOnRails: This is a test"
one, two, three = string.match(/(^.*)(:)(.*)/i).captures

p one   #=> "RyanOnRails"
p two   #=> ":"
p three #=> " This is a test"

일치하는 항목이 없으면 String#matchnil을 반환하므로 다음과 같이 더 잘 작동 할 수 있습니다.

if match = string.match(/(^.*)(:)(.*)/i)
  one, two, three = match.captures
end

하지만은 scan이를 위해 메이크업의 작은 감각을한다. 여전히 작업을 수행하므로 먼저 반환 된 배열을 평면화하면됩니다.one, two, three = string.scan(/(^.*)(:)(.*)/i).flatten


답변

당신은 사용할 수 있습니다 매치 또는 = ~ 대신에 당신에게 하나의 일치를 줄 것이며, 당신도 경기 데이터를 같은 방법으로 액세스하거나 특별한 경기 변수를 $ 1, $ 2, $ 3 사용할 수있는

다음과 같은 것 :

if ryan_string =~ /(^.*)(:)(.*)/i
   first = $1
   third = $3
end


답변

캡처 한 일치의 이름을 지정할 수 있습니다.

string = "RyanOnRails: This is a test"
/(?<one>^.*)(?<two>:)(?<three>.*)/i =~ string
puts one, two, three

문자열과 정규식의 순서를 반대로하면 작동하지 않습니다.


답변

좋은 생각인지 결정해야하지만 루비 정규 표현식은 (자동으로) 지역 변수를 정의 할 수 있습니다. 를 있습니다!

이 기능이 굉장한 지 완전히 미친지는 아직 확실하지 않지만 정규식은 지역 변수를 정의 할 수 있습니다.

ryan_string = "RyanOnRails: This is a test"
/^(?<webframework>.*)(?<colon>:)(?<rest>)/ =~ ryan_string
# This defined three variables for you. Crazy, but true.
webframework # => "RyanOnRails"
puts "W: #{webframework} , C: #{colon}, R: #{rest}"

( http://ruby-doc.org/core-2.1.1/Regexp.html 에서 “로컬 변수”를 검색하십시오).

참고 :
의견에서 지적했듯이 @toonsend ( https://stackoverflow.com/a/21412455 ) 에 의해이 질문에 대한 유사하고 이전 답변이 있음을 알 수 있습니다. 나는 내가 “도둑질”이라고 생각하지 않지만 칭찬에 공평하고 첫 번째 답변을 존중하고 싶다면 자유롭게 느끼십시오. 🙂 동물이 해를 입지 않았기를 바랍니다.


답변

scan() 문자열에서 정규식의 겹치지 않는 모든 일치 항목을 찾을 수 있으므로 예상하는 것처럼 그룹 배열을 반환하는 대신 배열 배열을 반환합니다.

을 사용 match()하고 다음을 사용하여 캡처 배열을 얻는 것이 더 좋습니다 MatchData#captures.

g1, g2, g3 = ryan_string.match(/(^.*)(:)(.*)/i).captures

그러나 다음과 같은 scan()경우에도이 작업을 수행 할 수 있습니다 .

g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)[0]


답변