2017-05-31 5 views
1

Ich möchte die Groß- und Kleinschreibung einer Zeichenfolge aus meinem Array TOKENS am Anfang einer anderen Zeichenfolge gefolgt von einem Leerzeichen oder dem Ende der Zeile.So passen Sie eine Zeichenfolge aus einem Array am Anfang einer anderen Zeichenfolge an

Mein Token-Array wie folgt aussieht:

2.4.0 :009 > data_col = ["M", "b", "Mabc", "abc m b"] 
=> ["M", "b", "Mabc", "abc m b"] 
... 
2.4.0 :015 > data_col.select{|string| string =~ /^[#{Regexp.union(TOKENS)}]([[:space:]]|$)/i } 
=> ["M", "b"] 

beide Dies wird passend zu dem „M:

2.4.0 :013 > TOKENS = ["m", "o"] 
=> ["m", "o"] 

Wenn ich versuche, von meinem Array jedes Element zu entsprechen, ist es die falschen Ergebnisse herauszuzupicken "und die" b "-Einträge, obwohl" b "nicht in meiner TOKENS-Liste erscheint. Wie ändere ich meinen regulären Ausdruck, sodass nur der richtige Wert "M" gefunden wird?

Ich benutze Ruby 2.4.

Antwort

3

würde ich verwenden:

TOKENS = ["m", "o"] 
DATA_COL = ["M", "b", "Mabc", "abc m b"] 
RE = /^(?:#{Regexp.union(TOKENS).source})(?: |$)/i 

DATA_COL.select{ |string| string[RE] } 
# => ["M"] 

es ein wenig nach unten brechen:

Regexp.union(TOKENS).source # => "m|o" 
/^(?:#{Regexp.union(TOKENS).source})(?: |$)/i # => /^(?:m|o)(?: |$)/i 

/^[#{Regexp.union(TOKENS)}]([[:space:]]|$)/i ist keine gute Idee, in einer Schleife. Jedes Mal zwingt Sie Ruby, das Muster zu erstellen. Effizienz ist wichtig in Schleifen, besonders in großen, also erstellen Sie das Muster außerhalb der Schleife und beziehen Sie sich dann auf das Muster im Inneren.

Das nächste Problem ist, dass Regexp.union ein Konzept des richtigen Fall hat, sollte es passen:

Regexp.union(TOKENS).to_s  # => "(?-mix:m|o)" 

Der (?-mix: Teil ist, wie die Regular Expression Engine die Fahnen für das Muster erinnert. Wenn das Muster in einem anderen Muster eingebettet ist, sie weiterhin wissen, was sie suchen sollten, uns was unsere Zähne fletschen und weinen:

/#{Regexp.union(TOKENS)}/i # => /(?-mix:m|o)/i 

Die Hinter i das Muster sagt es Fall ignorieren sollte, aber die i eingebettet ist nicht festgelegt, so dass es Fall honoriert. Und genau das bricht dein Muster.

Der Fix ist zu verwenden source beim Einbetten wie ich oben getan habe.

Weitere Informationen finden Sie im Regex "options" Abschnitt.

+0

Ein weiteres Problem ist, dass die ursprüngliche Regex-Änderung (erstellt von 'Regexp.union') innerhalb einer Zeichenklasse (die eckigen Klammern) hatte. – Max

+0

Obwohl dies nur dazu führt, dass 'b' fälschlicherweise Wahr zurückgibt, wenn Sie die' (? -mix:) 'Struktur haben. – Max

+0

Ah ja, es interpretiert '? -m' als Zeichenbereich innerhalb der Zeichenklasse, die' b' enthält. – Max

Verwandte Themen