2011-10-28 2 views
3

정규 표현식을 사용하여 일부 텍스트를 일치 시키려고합니다.정규 표현식에 대한 작업 - 반복 패턴

다음 패턴은 내가 수집하려고하는 것입니다.

@Identifier('VariableA', 'VariableB', 'VariableX', ..., 'VariableZ') 

고정 된 2 세트 또는 3 세트가 아닌 동적 변수를 얻고 싶습니다. 이렇게 할 방법이 있습니까?

\@(\w+)\W+(\w+)\W+(\w+)\W+(\w+) 

이 식별자를 캡처하고 최대 세 개의 변수에 : 나는 기존의 정규 표현식이있다.

편집 : 나만인가, 아니면 정규 표현식이 아닌가?

답변

3

이런 종류의 작업에는 scan을 사용하고 싶습니다. 기본 패턴이 될 것이다 :

단어 문자 당신에게 모든 연속적인 순서의 배열을 줄 것이다
s.scan(/\w+/) 

:

>> "@Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ')".scan(/\w+/) 
=> ["Identifier", "VariableA", "VariableB", "VariableX", "VariableZ"] 

을 당신이 임의의 물건을 주위와 패턴의 여러 인스턴스가있을 수 있습니다 말한다 그들. 당신은 중첩 된 scan들과 그 처리 할 수 ​​

당신은 배열의 배열을 줄 것이다
s.scan(/@(\w+)\(([^)]+?)\)/).map { |m| [ m.first, m.last.scan(/\w+/) ] } 

는, 각 내부 배열의 첫 번째 요소로 "식별자"부분이있을 것이다 그 "변수"부분에 배열로 두 번째 요소. 예를 들어 :

>> s = "pancakes @Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ') pancakes @Pancakes('one','two','three') eggs" 
>> s.scan(/@(\w+)\(([^)]+?)\)/).map { |m| [ m.first, m.last.scan(/\w+/) ] } 
=> [["Identifier", ["VariableA", "VariableB", "VariableX", "VariableZ"]], ["Pancakes", ["one", "two", "three"]]] 

당신은 당신의 "변수"비트 내부 탈출 따옴표를 직면 당신은 더 복잡한 뭔가를해야합니다 수합니다. 발현에


일부 노트 :

@   # A literal "@". 
(   # Open a group 
    \w+  # One more more ("+") word characters ("\w"). 
)   # Close the group. 
\(   # A literal "(", parentheses are used for group so we escape it. 
(   # Open a group. 
    [   # Open a character class. 
    ^)  # The "^" at the beginning of a [] means "not", the ")" isn't escaped because it doesn't have any special meaning inside a character class. 
    ]   # Close a character class. 
    +?   # One more of the preceding pattern but don't be greedy. 
)   # Close the group. 
\)   # A literal ")". 

당신은 정말 여기 [^)]+? 필요가 없습니다, 단지 [^)]+ 할 수 있지만,이 무슨 뜻인지 보통이기 때문에 습관에 의해 비 욕심 형태를 사용합니다. 그룹화는 @IdentifierVariable 부분을 분리하는 데 사용되므로 원하는 중첩 배열 출력을 쉽게 얻을 수 있습니다.

+0

이것은 완벽합니다! 정확히 내가 찾던 해결책이었습니다. 이제 어떻게 정규 표현식을 만들 었는지 배우십시오! 정말 고맙습니다! – Michael

+1

@ 마이클 : 당신을 위해 정규 표현식에 몇 가지 메모를 추가했습니다. –

+0

당신은 최고입니다! 이것에 대한 도움을 정말 고맙게 생각합니다. Ruby와 Regular Expressions에 더 익숙해 지려고 노력 중입니다. 나는 그런 식으로 논리적 인 NOT을 할 수 있다는 것을 몰랐다. 진심으로, 다시 한번 감사드립니다! – Michael

0

하지만 알렉스는 네가 똑같은 것을 네 번 붙잡고 싶다는 뜻이라고 생각합니다. 동일한 패턴이지만 다른 것들을 포착하려면 두 가지를 고려해야합니다.

반복. 펄에서는 'g'는 '글로벌'을 의미하고, 정규식가 호출 될 때마다, 그것은/다음/인스턴스를 일치한다는 것을 의미

while ($variable =~ /regex/g) { 

을 말할 수있다.

다른 옵션은 재귀입니다. 이처럼 정규식 쓰기 :

/(what you want)(.*)/ 

그런 다음, 당신은 역 참조 (1) 더 이상 일치 할 때까지 다음을 통해 재귀없는거야 먼저 배열에 푸시 할 수 있습니다 것, 그리고 역 참조 (2)를 포함 있습니다.

+0

Ruby에서 전역 식별자가 작동합니까? 나는 그렇게 생각하지 않는다. – Michael

+0

http://stackoverflow.com/questions/2293032/ruby-doesnt-recognize-the-g-flag-for-regex – Dan

0

간단하게 (\w+)을 사용할 수 있습니다.

  1. Identifier
  2. VariableA
  3. VariableB
  4. VariableX
  5. :

    는 결과가 될 것입니다 입력 문자열 @Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ')

    을 감안할 때

이것은 임의의 수의 변수에 적용됩니다.

나중에 참조 할 수 있도록 Rubular에있는 regexp 아이디어로 쉽고 재미있게 놀 수 있습니다.

+0

Rubular와 함께 놀았지만 여전히이 권리를 얻을 수 없습니다. 식별자와 변수 만 있으면됩니다. 하나씩 문자열을 선택하여이 데이터를 수동으로 추출 할 수 있지만 정규 표현식의 요점은 무엇입니까? 또한 솔루션이 너무 광범위합니다. 다른 단어 나 단어와 유사한 데이터를 캡쳐해야하기 이전이나 이후에 추가하면 불필요한 데이터를 캡처합니다. – Michael

0

따라서 식별자와 임의의 수의 변수를 캡처하는 방법이 있는지 묻습니다. 캡처를 지원하는 정규식 엔진에서만이 작업을 수행 할 수 있습니다. 여기서 그룹을 캡쳐 함은 동일한 것이 아닙니다. 모든 "변수"를 기억하고 싶습니다. 간단한 캡처 그룹에서는이 작업을 수행 할 수 없습니다.

루비가 지원하는지 여부는 모르지만 .NET과 새로운 PERL 6이이를 지원하는지 확신합니다.

두 가지 정규식을 사용할 수 있습니다. 예를 들어 식별자를 캡처하는 하나 ^\s*@(\w+)

및 모든 변수를 포착하기위한 다른 하나. result = subject.scan(/'[^']+'/)

관련 문제