Reguläre Ausdrücke (Regex) sind ein mächtiges Werkzeug für die Arbeit mit Strings in Elixir. Reguläre Ausdrücke in Elixir folgen der PCRE-Spezifikation (Perl Compatible Regular Expressions). String-Muster, die die Bedeutung des regulären Ausdrucks darstellen, werden zuerst kompiliert und dann verwendet, um einen String ganz oder teilweise zu matchen.
In Elixir ist der gebräuchlichste Weg, reguläre Ausdrücke zu erstellen, das ~r-Sigil. Sigils bieten syntaktischen Zucker als Abkürzung für häufige Aufgaben in Elixir. Um ein String-Literal zu matchen, können wir den String selbst als Muster nach dem Sigil verwenden.
~r/test/
Der =~/2-Operator ist nützlich, um mit einer Regex einen String zu matchen und ein boolean-Ergebnis zu erhalten.
"this is a test" =~ ~r/test/
# => true
Zwei Anmerkungen zur Verwendung von Sigils:
/ verwendet werden\) escapen
Wenn du einen Zeichenbereich mit eckigen Klammern [] angibst, definierst du eine Zeichenklasse. Sie matcht genau ein Zeichen aus der Menge der Zeichen in der Klasse. Du kannst auch einen Zeichenbereich wie a-z angeben, solange Anfang und Ende einen zusammenhängenden Bereich von Codepunkten darstellen.
regex = ~r/[a-z][ADKZ][0-9][!?]/
"jZ5!" =~ regex
# => true
"jB5?" =~ regex
# => false
Kurzschreibweisen für Zeichenklassen machen das Muster kompakter. Zum Beispiel:
\d Kurzform für [0-9] (jede Ziffer)\w Kurzform für [A-Za-z0-9_] (jedes „Wort“-Zeichen)\s Kurzform für [ \t\r\n\f] (jedes Whitespace-Zeichen)Wenn eine Kurzschreibweise für Zeichenklassen außerhalb eines Sigils verwendet wird, muss sie escaped werden: "\\d"
Alternativen verwenden | als Sonderzeichen, um auszudrücken, dass das eine oder das andere gematcht wird
regex = ~r/cat|bat/
"bat" =~ regex
# => true
"cat" =~ regex
# => true
Quantoren erlauben ein sich wiederholendes Muster im Regex. Sie wirken auf die Gruppe, die vor dem Quantor steht.
{N, M} wobei N die minimale Anzahl an Wiederholungen und M die maximale ist{N,} matcht N oder mehr Wiederholungen
{0,} kann auch als * geschrieben werden: null oder mehr Wiederholungen matchen{1,} kann auch als + geschrieben werden: eine oder mehr Wiederholungen matchen{,N} matcht bis zu N WiederholungenRunde Klammern () werden verwendet, um Gruppen und Captures zu kennzeichnen. Die Gruppe kann in manchen Fällen auch gecaptured werden, um sie zur weiteren Verwendung zurückzugeben. In Elixir können diese benannt oder unbenannt sein. Captures werden benannt, indem du ?<name> nach der öffnenden Klammer anhängst. Gruppen funktionieren als eine Einheit, zum Beispiel wenn ein Quantor folgt.
regex = ~r/(h)at/
Regex.replace(regex, "hat", "\\1op")
# => "hop"
regex = ~r/(?<letter_b>b)/
Regex.scan(regex, "blueberry", capture: :all_names)
# => [["b"], ["b"]]
Anker werden verwendet, um den regulären Ausdruck an den Anfang oder das Ende des Strings zu binden, der gematcht werden soll:
^ verankert am Anfang des Strings$ verankert am Ende des StringsDa ~r eine Abkürzung für "pattern" |> Regex.escape() |> Regex.compile!() ist, kannst du auch String-Interpolation verwenden, um ein Regex-Muster dynamisch aufzubauen:
anchor = "$"
regex = ~r/end of the line#{anchor}/
"end of the line?" =~ regex
# => false
"end of the line" =~ regex
# => true
Du sollst einen Dienst schreiben, der Ereignisse entgegennimmt. Jedes Ereignis hat ein zugehöriges Datum, aber dir fällt auf, dass an den Endpunkt deines Dienstes drei verschiedene Formate geschickt werden:
"01/01/1970""January 1, 1970""Thursday, January 1, 1970"Du erkennst, dass es gewisse Ähnlichkeiten zwischen ihnen gibt, und beschließt, einige zusammensetzbare Muster für reguläre Ausdrücke zu schreiben.
Implementiere day/0, month/0 und year/0, um ein String-Muster zurückzugeben, das, wenn es kompiliert wird, auf die numerischen Bestandteile in "01/01/1970" (dd/mm/yyyy) passt. Tag und Monat können als 1 oder 01 erscheinen (links mit Nullen aufgefüllt).
"31" =~ DateParser.day() |> Regex.compile!()
# => true
"12" =~ DateParser.month() |> Regex.compile!()
# => true
"1970" =~ DateParser.year() |> Regex.compile!()
# => true
Implementiere day_names/0 und month_names/0, um ein String-Muster zurückzugeben, das, wenn es kompiliert wird, auf den ausgeschriebenen Wochentag bzw. den ausgeschriebenen Monat des Jahres passt.
"Tuesday" =~ DateParser.day_names() |> Regex.compile!()
# => true
"June" =~ DateParser.month_names() |> Regex.compile!()
# => true
Implementiere capture_day/0, capture_month/0, capture_year/0, capture_day_name/0 und capture_month_name/0, um ein String-Muster zurückzugeben, das die jeweiligen Bestandteile unter den Namen "day", "month", "year", "day_name", "month_name" erfasst.
DateParser.capture_month_name()
|> Regex.compile!()
|> Regex.named_captures("December")
# => %{"month_name" => "December"}
Implementiere capture_numeric_date/0, capture_month_name_date() und capture_day_month_name_date/0, um ein String-Muster zurückzugeben, das die Bestandteile aus Teil 3 mit dem jeweiligen Datumsformat erfasst:
"01/01/1970"
"January 1, 1970"
"Thursday, January 1, 1970"
DateParser.capture_numeric_date()
|> Regex.compile!()
|> Regex.named_captures("01/01/1970")
# => %{"day" => "01", "month" => "01", "year" => "1970"}
Implementiere match_numeric_date/0, match_month_name_date/0 und match_day_month_name_date/0, um einen kompilierten regulären Ausdruck zurückzugeben, der nur auf das Datum passt und der außerdem die Bestandteile erfassen kann.
"Thursday, January 1, 1970 was the Unix epoch." =~ DateParser.match_day_month_name_date()
# => false
"Thursday, January 1, 1970" =~ DateParser.match_day_month_name_date()
# => true
DateParser.match_day_month_name_date()
|> Regex.named_captures("Thursday, January 1, 1970")
# => %{
# "day" => "1",
# "day_name" => "Thursday",
# "month_name" => "January",
# "year" => "1970"
# }
Melde dich bei Exercism an, um Elixir mit 58 Konzepte168 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.