정규식의 모든 항목을 일치시키는 방법


586

Ruby에서 정규 표현식과 일치하는 모든 항목을 찾는 빠른 방법이 있습니까? Ruby STL에서 Regex 객체를 살펴본 결과 Google에서 아무 소용이 없었습니다.


3
나는 이것이 정규식 패턴을 찾기 위해 어떻게 문자열을 검색 할 수 있고 몹시 혼란 스러웠
는지를 읽었다

답변:


821

사용 scan하면 트릭을 수행해야합니다.

string.scan(/regex/)

9
그러나이 사건에 어떻게 접해 있습니까? "match me!". scan (/.../) = [ "mat", "ch" "나!" ]하지만, /.../의 모든 항목은 [ "매트", "ATC", "TCH", "채널", ...] 될 것
마이클 디킨스

13
그렇지 않을 것입니다. /.../는 욕심 많은 정규 표현식입니다. 일치하는 콘텐츠는 역 추적하지 않습니다. 게으른 정규 표현식을 사용하려고 시도해도 충분하지 않을 수도 있습니다. 정규 표현식 을 정확하게 표현하기 위해 정규 표현식 문서 ruby-doc.org/core-1.9.3/Regexp.html 을 살펴보십시오 :)
Jean

49
이것은 Ruby WTF처럼 보입니다 ... 왜 다른 정규 표현식과 함께 Regexp 대신 String에 있습니까? 그것도 정규 표현식에 대한 문서의 아무 곳이나 언급되지 않은
Anentropic

9
그것은 Regex가 아닌 String에서 정의되고 호출 되었기 때문입니다 ...하지만 실제로 의미가 있습니다. 정규식을 작성하여 Regex # match를 사용하여 모든 일치 항목을 캡처하고 캡처 된 그룹을 반복 할 수 있습니다. 여기서 부분 일치 함수를 작성하고 주어진 문자열에 여러 번 적용하기를 원하지만 이는 Regexp의 책임이 아닙니다. 더 나은 이해를 위해 스캔 구현을 확인하는 것이 좋습니다. ruby-doc.org/core-1.9.3/String.html#method-i-scan
Jean

9
@MichaelDickens :이 경우을 사용할 수 있습니다 /(?=(...))/.
Konrad Borowski

67

일치하는 모든 문자열을 찾으려면 String의 scan메소드를 사용하십시오.

str = "A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"
str.scan(/\d+/)
#=> ["54", "3", "1", "7", "3", "36", "0"]

MatchDataRegexp match메소드가 리턴 한 오브젝트의 유형 인 원하는 경우 다음을 사용하십시오.

str.to_enum(:scan, /\d+/).map { Regexp.last_match }
#=> [#<MatchData "54">, #<MatchData "3">, #<MatchData "1">, #<MatchData "7">, #<MatchData "3">, #<MatchData "36">, #<MatchData "0">]

사용의 이점은 다음 MatchData과 같은 방법을 사용할 수 있다는 것입니다 offset.

match_datas = str.to_enum(:scan, /\d+/).map { Regexp.last_match }
match_datas[0].offset(0)
#=> [2, 4]
match_datas[1].offset(0)
#=> [7, 8]

더 알고 싶다면 다음 질문을보십시오.

특수 변수에 대해 읽기 $&, $', $1, $2루비 너무 도움이 될 것입니다.


12

그룹이있는 정규 표현식이있는 경우 :

str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"
re=/(\d+)[m-t]/

String의 scan메소드를 사용 하여 일치하는 그룹을 찾을 수 있습니다.

str.scan re
#> [["54"], ["1"], ["3"]]

일치하는 패턴을 찾으려면

str.to_enum(:scan,re).map {$&}
#> ["54m", "1t", "3r"]

str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]보다 더 관용적 인str.to_enum(:scan,re).map {$&}
양철 남자

아마 당신은 오해했을 것입니다. 내가 대답 한 사용자의 예에 대한 정규식은 다음과 같습니다. 작성 /(\d+)[m-t]/하지 않음 /\d+[m-t]/: re = /(\d+)[m-t]/; str.scan(re)동일 str.scan(/(\d+)[mt]/)하지만 #> [["" 54 "], [" 1 "], [" 3 "]]가 아닙니다 "54m", "1t", "3r"]. 질문 : 그룹과의 정규 표현식이 있고 정규 패턴을 변경하지 않고 모든 패턴을 캡처하려는 경우 표현 (그룹을 떠나는), 어떻게 할 수 있습니까? 이런 의미에서, 비록 조금 비밀스럽고 읽기 어려울지라도 가능한 해결책은 다음과 같습니다.str.to_enum(:scan,re).map {$&}
MVP

-1

사용할 수 있습니다 string.scan(your_regex).flatten. 정규식에 그룹이 포함되어 있으면 단일 일반 배열로 반환됩니다.

string = "A 54mpl3 string w1th 7 numbers scatter3r ar0und"
your_regex = /(\d+)[m-t]/
string.scan(your_regex).flatten
=> ["54", "1", "3"]

정규식도 명명 된 그룹 일 수 있습니다.

string = 'group_photo.jpg'
regex = /\A(?<name>.*)\.(?<ext>.*)\z/
string.scan(regex).flatten

당신은 또한 사용할 수 있습니다 gsub당신이 MatchData을 원한다면 그냥 또 하나의 방법입니다.

str.gsub(/\d/).map{ Regexp.last_match }

에서 그룹을 제거하면를 your_regex = /(\d+)[m-t]/사용할 필요가 없습니다 flatten. 마지막 예제는 last_match이 경우 아마도 안전한 것을 사용하지만 전역 적이며 호출하기 전에 정규 표현식이 일치하면 덮어 쓸 수 있습니다 last_match. 대신 사용 아마 더 안전 string.match(regex).captures # => ["group_photo", "jpg"]이나 string.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]패턴 및 필요에 따라 다른 답변에서와 같이.
Tin Man
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.