[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#match
nil을 반환하므로 다음과 같이 더 잘 작동 할 수 있습니다.
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]