2016-12-07 2 views
4

Ich möchte alle Übereinstimmungen innerhalb einer gegebenen Zeichenfolge finden, einschließlich überlappender Übereinstimmungen. Wie könnte ich es erreichen?Überlappende Regexp-Übereinstimmungen suchen

# Example 
"a-b-c".???(/\w-\w/) # => ["a-b", "b-c", "c-d"] expected 

# Solution without overlapped results 
"a-b-c-d".scan(/\w-\w/) # => ["a-b", "c-d"], but "b-c" is missing 

Antwort

5

Verwendung in einem positiven Look-Ahead-Erfassung:

"a-b-c-d".scan(/(?=(\w-\w))/).flatten 
# => ["a-b", "b-c", "c-d"] 

Siehe Ruby demo

+0

Funktioniert perfekt, auch mit komplexen Mustern. "abaca" .scan (/ (? = (\ w) (?: (?! \ 1) (\ w)) \ 1) /) # => [["a", "b"], [" a "," c "]]". – sschmeck

+0

Die Inspektion scheint nicht nur unnötig, sondern schädlich für das Endergebnis. –

+1

... oder positiv lookbehind: '" a-b-c-d ".scan (/ (? <= (\ W- \ w)) /). –

3

Ich schlage vor, eine nicht-regex Lösung:

"a-b-c-d".delete('-').each_char.each_cons(2).map { |s| s.join('-') } 
    #=> ["a-b", "b-c", "c-d"] 

oder

"a-b-c-d".each_char.each_cons(3).select.with_index { |_,i| i.even? }.map(&:join) 
    #=> ["a-b", "b-c", "c-d"] 

oder

enum = "a-b-c-d".each_char 
a = [] 
loop do 
    a << "%s%s%s" % [enum.next, enum.next, enum.peek] 
end 
a #=> ["a-b", "b-c", "c-d"] 
+1

Ihre letzte Technik ist sehr, sehr ordentlich. –

+0

Schöne Antwort, aber ich fragte explizit nach einer Regexp. Das obige Muster war nur das einfachste, das ich gefunden habe, um mein Problem zu erklären. Das Muster, das ich tatsächlich verwende, ist '(\ w) (?: (?! \ 1) (\ w)) \ 1'. – sschmeck