Ruby Language
Reguläre Ausdrücke und auf Regex basierende Vorgänge
Suche…
Gruppen, benannt und anders.
Ruby erweitert die Standardgruppensyntax (...)
um eine benannte Gruppe (?<name>...)
. Dies ermöglicht das Extrahieren nach Namen, anstatt zu zählen, wie viele Gruppen Sie haben.
name_reg = /h(i|ello), my name is (?<name>.*)/i #i means case insensitive
name_input = "Hi, my name is Zaphod Beeblebrox"
match_data = name_reg.match(name_input) #returns either a MatchData object or nil
match_data = name_input.match(name_reg) #works either way
if match_data.nil? #Always check for nil! Common error.
puts "No match"
else
match[0] #=> "Hi, my name is Zaphod Beeblebrox"
match[1] #=> "i" #the first group, (i|ello)
match[2] #=> "Zaphod Beeblebrox"
#Because it was a named group, we can get it by name
match[:name] #=> "Zaphod Beeblebrox"
match["name"] #=> "Zaphod Beeblebrox"
puts "Hello #{match[:name]}!"
end
Der Index der Übereinstimmung wird basierend auf der Reihenfolge der linken Klammern gezählt (wobei der gesamte reguläre Ausdruck die erste Gruppe bei Index 0 ist).
reg = /(((a)b)c)(d)/
match = reg.match 'abcd'
match[0] #=> "abcd"
match[1] #=> "abc"
match[2] #=> "ab"
match[3] #=> "a"
match[4] #=> "d"
= ~ Operator
if /hay/ =~ 'haystack'
puts "There is hay in the word haystack"
end
Hinweis: Die Reihenfolge ist signifikant . Obwohl 'haystack' =~ /hay/
in den meisten Fällen gleichwertig ist, können die Nebenwirkungen unterschiedlich sein:
- Von benannten Erfassungsgruppen erfasste Zeichenfolgen werden lokalen Variablen nur zugewiesen, wenn
Regexp#=~
aufgerufen wird (regexp =~ str
); - Da der rechte Operand möglicherweise ein beliebiges Objekt ist, wird für
regexp =~ str
entwederRegexp#=~
oderString#=~
aufgerufen.
Beachten Sie, dass dies keinen True / False-Wert zurückgibt. Stattdessen wird entweder der Index der Übereinstimmung zurückgegeben, wenn er gefunden wird, oder Null, wenn er nicht gefunden wird. Da alle ganzen Zahlen in Rubin wahr sind (einschließlich 0) und Null falsch ist, funktioniert dies. Wenn Sie einen booleschen Wert wünschen, verwenden Sie #===
wie in einem anderen Beispiel gezeigt .
Quantifizierer
Mit Quantifizierern können Sie die Anzahl der wiederholten Zeichenfolgen angeben.
Null oder eins:
/a?/
Null oder viele:
/a*/
Eins oder viele:
/a+/
Genaue Anzahl:
/a{2,4}/ # Two, three or four /a{2,}/ # Two or more /a{,4}/ # Less than four (including zero)
Quantifizierer sind standardmäßig gierig , was bedeutet, dass sie so viele Zeichen wie möglich benötigen, während sie trotzdem eine Übereinstimmung herstellen. Normalerweise fällt das nicht auf:
/(?<site>.*) Stack Exchange/ =~ 'Motor Vehicle Maintenance & Repair Stack Exchange'
Der angegebene site
der Erfassungsgruppe wird wie erwartet auf "Kfz-Wartung und Reparatur" gesetzt. Wenn 'Stack Exchange' jedoch ein optionaler Teil der Zeichenfolge ist (da dies stattdessen 'Stack Overflow' sein könnte), funktioniert die naive Lösung nicht wie erwartet:
/(?<site>.*)( Stack Exchange)?/
Diese Version stimmt immer noch überein, aber das benannte Capture enthält "Stack Exchange", da *
diese Charaktere gierig frisst. Die Lösung besteht darin, ein weiteres Fragezeichen hinzuzufügen, um das *
faul zu machen:
/(?<site>.*?)( Stack Exchange)?/
Anhängen ?
zu jedem Quantifizierer wird es faul machen.
Charakterklassen
Beschreibt Bereiche von Symbolen
Sie können Symbole explizit auflisten
/[abc]/ # 'a' or 'b' or 'c'
Oder verwenden Sie Bereiche
/[a-z]/ # from 'a' to 'z'
Es ist möglich, Bereiche und einzelne Symbole zu kombinieren
/[a-cz]/ # 'a' or 'b' or 'c' or 'z'
Führender Bindestrich ( -
) wird als Zeichen behandelt
/[-a-c]/ # '-' or 'a' or 'b' or 'c'
Klassen können negativ sein, wenn Symbole mit ^
vorangestellt werden
/[^a-c]/ # Not 'a', 'b' or 'c'
Es gibt einige Abkürzungen für weit verbreitete Klassen und spezielle Charaktere sowie Leitungsenden
^ # Start of line
$ # End of line
\A # Start of string
\Z # End of string, excluding any new line at the end of string
\z # End of string
. # Any single character
\s # Any whitespace character
\S # Any non-whitespace character
\d # Any digit
\D # Any non-digit
\w # Any word character (letter, number, underscore)
\W # Any non-word character
\b # Any word boundary
\n
wird einfach als neue Zeile verstanden
Um einem reservierten Zeichen zu entkommen, wie /
oder []
und anderen, verwenden Sie den Backslash (linker Schrägstrich)
\\ # => \
\[\] # => []
Reguläre Ausdrücke in Case Statements
Sie können mit einer switch-Anweisung testen, ob eine Zeichenfolge mit mehreren regulären Ausdrücken übereinstimmt.
Beispiel
case "Ruby is #1!"
when /\APython/
puts "Boooo."
when /\ARuby/
puts "You are right."
else
puts "Sorry, I didn't understand that."
end
Dies funktioniert, weil case-Anweisungen mit dem Operator ===
auf Gleichheit ===
werden, nicht mit dem Operator ==
. Wenn sich ein Regex mit ===
auf der linken Seite eines Vergleichs befindet, ===
er eine Zeichenfolge, um zu sehen, ob sie übereinstimmt.
Regexp definieren
Ein Regexp kann auf drei verschiedene Arten in Ruby erstellt werden.
Schrägstriche verwenden:
/ /
mit
%r{}
mit
Regex.new
#The following forms are equivalent regexp_slash = /hello/ regexp_bracket = %r{hello} regexp_new = Regexp.new('hello') string_to_match = "hello world!" #All of these will return a truthy value string_to_match =~ regexp_slash # => 0 string_to_match =~ regexp_bracket # => 0 string_to_match =~ regexp_new # => 0
Spiel? - Boolesches Ergebnis
Gibt " true
oder " false
Dies gibt an, ob der reguläre Ausdruck übereinstimmt oder nicht, ohne $~
und andere verwandte Variablen zu aktualisieren. Wenn der zweite Parameter vorhanden ist, gibt er die Position in der Zeichenfolge an, um die Suche zu beginnen.
/R.../.match?("Ruby") #=> true
/R.../.match?("Ruby", 1) #=> false
/P.../.match?("Ruby") #=> false
Ruby 2.4+
Allgemeine schnelle Verwendung
Reguläre Ausdrücke werden in Methoden häufig als Parameter verwendet, um zu überprüfen, ob andere Zeichenfolgen vorhanden sind, oder um Zeichenfolgen zu suchen und / oder zu ersetzen.
Sie werden oft folgendes sehen:
string = "My not so long string"
string[/so/] # gives so
string[/present/] # gives nil
string[/present/].nil? # gives true
Sie können dies also einfach als Überprüfung verwenden, ob eine Zeichenfolge eine Teilzeichenfolge enthält
puts "found" if string[/so/]
Fortgeschrittener, aber immer noch kurz und schnell: Suchen Sie mithilfe des zweiten Parameters nach einer bestimmten Gruppe. In diesem Beispiel ist 2 der zweite, da die Nummerierung bei 1 und nicht bei 0 beginnt. Eine Gruppe ist das, was in Klammern steht.
string[/(n.t).+(l.ng)/, 2] # gives long
Wird auch häufig verwendet: Suchen und Ersetzen mit sub
oder gsub
, \1
ergibt die erste gefundene Gruppe, \2
die zweite:
string.gsub(/(n.t).+(l.ng)/, '\1 very \2') # My not very long string
Das letzte Ergebnis wird gespeichert und kann in den folgenden Zeilen verwendet werden
$2 # gives long