Tipps und Fehlerbehebung beim Schreiben von Parsern

In diesem Dokument werden Probleme beschrieben, die beim Schreiben von Parsercode auftreten können.

Beim Schreiben von Parsercode können Fehler auftreten, wenn Parsing-Anweisungen nicht wie erwartet funktionieren. Mögliche Fehlersituationen:

  • Ein Grok-Muster schlägt fehl
  • Ein rename- oder replace-Vorgang schlägt fehl
  • Syntaxfehler im Parsercode

Häufige Praktiken im Parsercode

In den folgenden Abschnitten werden die Best Practices, Tipps und Lösungen beschrieben. um Ihnen bei der Fehlerbehebung zu helfen.

Vermeiden Sie die Verwendung von Punkten oder Bindestrichen in Variablennamen

Die Verwendung von Bindestrichen und Punkten in Variablennamen kann zu unerwartetem Verhalten führen. häufig bei merge-Vorgängen zum Speichern von Werten in UDM-Feldern. Möglicherweise treten auch zeitweise Parsing-Probleme auf.

Verwenden Sie beispielsweise folgende Variablennamen nicht:

  • my.variable.result
  • my-variable-result

Verwenden Sie stattdessen den folgenden Variablennamen: my_variable_result.

Verwenden Sie keine Begriffe mit besonderer Bedeutung als Variablennamen.

Bestimmte Wörter wie event und timestamp können im Parser eine besondere Bedeutung haben Code.

Der String event wird häufig für einen einzelnen UDM-Eintrag verwendet und in folgenden Fällen verwendet: Die @output-Anweisung. Eine Lognachricht enthält ein Feld mit dem Namen event oder wenn Sie eine Zwischenvariable namens event definieren und die wenn der Parsercode das Wort event in der @output-Anweisung verwendet, erhältst du erhalten Sie eine Fehlermeldung zu einem Namenskonflikt.

Benennen Sie die Zwischenvariable in einen anderen Namen um oder verwenden Sie den Begriff event1 wie ein Präfix in UDM-Feldnamen und in der @output-Anweisung.

Das Wort timestamp steht für den erstellten Zeitstempel des ursprünglichen Rohlogs. A wird der in dieser Zwischenvariablen festgelegte Wert im UDM-Feld „metadata.event_timestamp“. Der Begriff @timestamp steht für das Datum und die Zeit, zu der das Rohlog geparst wurde, um einen UDM-Eintrag zu erstellen.

Im folgenden Beispiel wird das UDM-Feld metadata.event_timestamp auf das Datum gesetzt. und die Zeit, zu der das Rohprotokoll geparst wurde.

 # Save the log parse date and time to the timestamp variable
  mutate {
     rename => {
       "@timestamp" => "timestamp"
     }
   }

Im folgenden Beispiel wird das UDM-Feld metadata.event_timestamp auf das Datum und Zeit, die aus dem ursprünglichen Rohprotokoll extrahiert und in der Zwischendatei when gespeichert wird .

   # Save the event timestamp to timestamp variable
   mutate {
     rename => {
       "when" => "timestamp"
     }
   }

Folgende Begriffe dürfen nicht als Variablen verwendet werden:

  • CollectionZeitstempel
  • createtimestamp
  • event
  • filename
  • Nachricht
  • Namespace
  • Ausgabe
  • onerrorcount
  • timestamp
  • Zeitzone

Speichern Sie jeden Datenwert in einem separaten UDM-Feld

Speichern Sie mehrere Felder nicht in einem einzelnen UDM-Feld, indem Sie sie mit einem Trennzeichen. Hier ein Beispiel:

"principal.user.first_name" => "first:%{first_name},last:%{last_name}"

Speichern Sie stattdessen jeden Wert in einem separaten UDM-Feld.

"principal.user.first_name" => "%{first_name}"
"principal.user.last_name" => "%{last_name}"

Verwenden Sie im Code Leerzeichen statt Tabulatoren

Verwenden Sie im Parsercode keine Tabulatoren. Verwenden Sie nur Leerzeichen und rücken Sie jeweils zwei Leerzeichen ein.

Nicht mehrere Zusammenführungsaktionen in einem Vorgang ausführen

Wenn Sie mehrere Felder in einem Vorgang zusammenführen, kann dies zu uneinheitliche Ergebnisse. Platzieren Sie merge-Anweisungen stattdessen in separate Geschäftsabläufe.

Ersetzen Sie beispielsweise das folgende Beispiel:

mutate {
  merge => {
      "security_result.category_details" => "category_details"
      "security_result.category_details" => "super_category_details"
  }
}

durch diesen Codeblock:

mutate {
  merge => {
    "security_result.category_details" => "category_details"
  }
}

mutate {
  merge => {
    "security_result.category_details" => "super_category_details"
  }
}

Bedingte Ausdrücke if und if else auswählen

Wenn der bedingte Wert, den Sie testen möchten, immer nur eine Verwenden Sie dann die bedingte if else-Anweisung. Dieser Ansatz ist etwas stärker effizient zu gestalten. Wenn Sie jedoch ein Szenario haben, bei dem der getestete Wert mehr als einmal verwenden, verwenden Sie mehrere unterschiedliche if-Anweisungen und ordnen Sie die Anweisungen vom allgemeinsten zum spezifischsten Fall.

Wählen Sie einen repräsentativen Satz von Protokolldateien aus, um Parseränderungen zu testen

Eine bewährte Methode besteht darin, Parsercode mithilfe von Rohlogbeispielen mit einer umfassenden in verschiedenen Formaten. So können Sie eindeutige Logs oder Grenzfälle ermitteln, die der Parser möglicherweise verarbeiten muss.

Beschreibende Kommentare zum Parsercode hinzufügen

Fügen Sie dem Parsercode Kommentare hinzu, die erklären, warum die Anweisung wichtig ist, als das, was die Anweisung tut. Der Kommentar hilft allen, die den Parser verwalten um dem Ablauf zu folgen. Hier ein Beispiel:

# only assign a Namespace if the source address is RFC 1918 or Loopback IP address
if [jsonPayload][id][orig_h] =~ /^(127(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{3\}$)|(10(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{3\}$)|(192\.168(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{2\}$)|(172\.(?:1[6-9]|2\d|3[0-1])(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\{2\}$)/ {
  mutate {
    replace => {
      "event1.idm.read_only_udm.principal.namespace" => "%{resource.labels.project_id}"
    }
  }
}

Zwischenvariablen frühzeitig initialisieren

Initialisieren Sie die Zwischendatei, bevor Sie Werte aus dem ursprünglichen Rohlog extrahieren. Variablen, die zum Speichern von Testwerten verwendet werden.

Dadurch wird verhindert, dass ein Fehler zurückgegeben wird, der darauf hinweist, dass die Zwischenvariable existiert nicht.

Mit der folgenden Anweisung wird der Wert in der Variablen product das UDM-Feld metadata.product_name.

mutate{
  replace => {
    "event1.idm.read_only_udm.metadata.product_name" => "%{product}"
  }
}

Wenn die Variable product nicht vorhanden ist, wird der folgende Fehler angezeigt:

"generic::invalid_argument: pipeline failed: filter mutate (4) failed: replace failure: field \"event1.idm.read_only_udm.metadata.product_name\": source field \"product\": field not set"

Sie können eine on_error-Anweisung hinzufügen, um den Fehler abzufangen. Hier ein Beispiel:

mutate{
  replace => {
    "event1.idm.read_only_udm.metadata.product_name" => "%{product}"
    }
  on_error => "_error_does_not_exist"
  }

Mit der vorherigen Beispielanweisung wird der Parsing-Fehler erfolgreich in einen boolesche Zwischenvariable namens _error_does_not_exist. Nicht ermöglichen Ihnen die Verwendung der Variable product in einer bedingten Anweisung, z. B. if. Hier ein Beispiel:

if [product] != "" {
  mutate{
    replace => {
      "event1.idm.read_only_udm.metadata.product_name" => "%{product}"
    }
  }
  on_error => "_error_does_not_exist"
}

Im vorherigen Beispiel wird der folgende Fehler zurückgegeben, da die Bedingungsklausel if unterstützt keine on_error-Anweisungen:

"generic::invalid_argument: pipeline failed: filter conditional (4) failed: failed to evaluate expression: generic::invalid_argument: "product" not found in state data"

Um dieses Problem zu lösen, fügen Sie einen separaten Anweisungsblock hinzu, der die Variablen vor dem Ausführen der Extraktionsfilteranweisungen (json, csv, xml, kv oder grok) hinzu. Folgendes ist ein Beispiel.

filter {
  # Initialize intermediate variables for any field you will use for a conditional check
  mutate {
    replace => {
      "timestamp" => ""
      "does_not_exist" => ""
    }
  }

  # load the logs fields from the message field
  json {
    source         => "message"
    array_function => "split_columns"
    on_error       => "_not_json"
  }
}

Das aktualisierte Snippet des Parsercodes verarbeitet die verschiedenen Szenarien mithilfe eines bedingte Anweisung, um zu prüfen, ob das Feld vorhanden ist. Darüber hinaus enthält der Mit der on_error-Anweisung werden mögliche Fehler verarbeitet.

SHA-256 in base64 konvertieren

Im folgenden Beispiel wird der SHA-256-Wert extrahiert, in base64 codiert und der codierten Daten in einen hexadezimalen String um und ersetzt dann bestimmte Felder durch die extrahierten und verarbeiteten Werte.

if [Sha256] != "" 
{
  base64
  {
  encoding => "RawStandard"
  source => "Sha256"
  target => "base64_sha256"
  on_error => "base64_message_error"
  }
  mutate
  {
    convert =>
    {
      "base64_sha256" => "bytestohex"
    }
    on_error => "already_a_string"
  }
  mutate
  {
    replace => 
  {
     "event.idm.read_only_udm.network.tls.client.certificate.sha256" => "%{base64_sha256}"
     "event.idm.read_only_udm.target.resource.name" => "%{Sha256}"
  }
  }
}

Fehler in Parser-Anweisungen verarbeiten

Eingehende Protokolle können ein unerwartetes Protokollformat haben oder schlecht formatierte Daten enthalten.

Sie können den Parser so erstellen, dass diese Fehler behandelt werden. Es empfiehlt sich, on_error-Handler in den Extraktionsfilter und dann die Zwischenvariable testen, bevor Sie mit dem nächsten Segment der Parserlogik fortfahren.

Im folgenden Beispiel wird der Extraktionsfilter json mit einem on_error verwendet , um die boolesche Variable _not_json festzulegen. Wenn _not_json auf true bedeutet dies, dass der eingehende Logeintrag nicht im gültigen JSON-Format vorkam und der Logeintrag wurde nicht erfolgreich geparst. Wenn die Variable _not_json false ist, Der eingehende Logeintrag hatte ein gültiges JSON-Format.

 # load the incoming log from the default message field
  json {
    source         => "message"
    array_function => "split_columns"
    on_error       => "_not_json"
  }

Sie können auch testen, ob ein Feld das richtige Format hat. Im folgenden Beispiel Prüft, ob _not_json auf true gesetzt ist. Dies weist darauf hin, dass das Log nicht im erwartete Format.

 # Test that the received log matches the expected format
  if [_not_json] {
    drop { tag => "TAG_MALFORMED_MESSAGE" }
  } else {
    # timestamp is always expected
    if [timestamp] != "" {

      # ...additional parser logic goes here …

    } else {

      # if the timestamp field does not exist, it's not a log source
      drop { tag => "TAG_UNSUPPORTED" }
    }
  }

Dadurch wird sichergestellt, dass das Parsen nicht fehlschlägt, wenn Logs mit einem falschen Format aufgenommen werden. für den angegebenen Logtyp.

Verwenden Sie den Filter drop mit der Variablen tag, damit die Bedingung im Tabelle mit Aufnahmemesswerten in BigQuery.

  • TAG_UNSUPPORTED
  • TAG_MALFORMED_ENCODING
  • TAG_MALFORMED_MESSAGE
  • TAG_NO_SECURITY_VALUE

Der Filter drop verhindert, dass der Parser das Rohlog verarbeitet und die Felder normalisiert. und einen UDM-Eintrag erstellen. Das ursprüngliche Rohlog wird weiterhin in Google Security Operations aufgenommen und können mit der Rohprotokollsuche in Google Security Operations durchsucht werden.

Der an die Variable tag übergebene Wert wird im drop_reason_code gespeichert: im Feld Tabelle mit Aufnahmemesswerten. Sie können eine Ad-hoc-Abfrage für die Tabelle wie folgt ausführen:

SELECT
  log_type,
  drop_reason_code,
  COUNT(drop_reason_code) AS count
FROM `datalake.ingestion_metrics`
GROUP BY 1,2
ORDER BY 1 ASC

Validierungsfehler beheben

Beim Erstellen eines Parsers können bei der Validierung Fehler auftreten, Beispiel: Im UDM-Eintrag wurde kein Pflichtfeld festgelegt. Der Fehler könnte etwa so aussehen: Folgendes:

Error: generic::unknown: invalid event 0: LOG_PARSING_GENERATED_INVALID_EVENT: "generic::invalid_argument: udm validation failed: target field is not set"

Der Parsercode wird erfolgreich ausgeführt, der generierte UDM-Eintrag jedoch nicht Schließt alle erforderlichen UDM-Felder ein, wie durch den Wert definiert, der auf metadata.event_type gesetzt ist. Die Im Folgenden finden Sie weitere Beispiele, die diesen Fehler verursachen können:

  • Wenn metadata.event_type den Wert USER_LOGIN hat und das UDM-Feld target.user value nicht festgelegt ist.
  • Wenn metadata.event_type NETWORK_CONNECTION ist und der target.hostnameUDM-Feld ist nicht festgelegt.

Weitere Informationen zum UDM-Feld „metadata.event_type“ und zum Pflichtfeld finden Sie im Leitfaden zur Verwendung von UMs.

Eine Möglichkeit zur Behebung dieses Fehlertyps besteht darin, zuerst statische Werte auf UDM festzulegen. . Nachdem Sie alle erforderlichen UDM-Felder definiert haben, prüfen Sie das ursprüngliche Rohlog, um zu sehen, welche Werte zum Parsen und Speichern im UDM-Eintrag. Wenn das ursprüngliche Rohprotokoll bestimmte Felder enthalten, müssen Sie ggf. Standardwerte festlegen.

Es folgt eine Beispielvorlage, die für den Ereignistyp USER_LOGIN spezifisch ist und die veranschaulicht diesen Ansatz.

Beachten Sie Folgendes:

  • Die Vorlage initialisiert Zwischenvariablen und legt jede auf einen statischen String fest.
  • Mit dem Code im Abschnitt Feldzuweisung werden die Werte in Zwischenvariablen festgelegt. zu UDM-Feldern.

Sie können diesen Code erweitern, indem Sie zusätzliche Zwischenvariablen und UDM-Felder hinzufügen. Nachdem Sie alle UDM-Felder identifiziert haben, die ausgefüllt werden müssen, gehen Sie so vor:

  • Fügen Sie im Abschnitt Eingabekonfiguration Code hinzu, mit dem Felder aus das ursprüngliche Rohprotokoll und legt die Werte auf die Zwischenvariablen fest.

  • Fügen Sie im Abschnitt Datum extrahieren Code hinzu, der den Zeitstempel des Ereignisses extrahiert. aus dem ursprünglichen Rohlog, transformiert es und legt es auf die Zwischenvariable fest.

  • Ersetzen Sie bei Bedarf den initialisierten Wert, der in jeder Zwischenvariablen festgelegt wurde, durch einen leeren String.

filter {
 mutate {
   replace => {
     # UDM > Metadata
     "metadata_event_timestamp"    => ""
     "metadata_vendor_name"        => "Example"
     "metadata_product_name"       => "Example SSO"
     "metadata_product_version"    => "1.0"
     "metadata_product_event_type" => "login"
     "metadata_product_log_id"     => "12345678"
     "metadata_description"        => "A user logged in."
     "metadata_event_type"         => "USER_LOGIN"

     # UDM > Principal
     "principal_ip"       => "192.168.2.10"

     # UDM > Target
     "target_application"            => "Example Connect"
     "target_user_user_display_name" => "Mary Smith"
     "target_user_userid"            => "mary@example.com"

     # UDM > Extensions
     "auth_type"          => "SSO"
     "auth_mechanism"     => "USERNAME_PASSWORD"

     # UDM > Security Results
     "securityResult_action"         => "ALLOW"
     "security_result.severity"       => "LOW"

   }
 }

 # ------------ Input Configuration  --------------
  # Extract values from the message using one of the extraction filters: json, kv, grok

 # ------------ Date Extract  --------------
 # If the  date {} function is not used, the default is the normalization process time

  # ------------ Field Assignment  --------------
  # UDM Metadata
  mutate {
    replace => {
      "event1.idm.read_only_udm.metadata.vendor_name"        =>  "%{metadata_vendor_name}"
      "event1.idm.read_only_udm.metadata.product_name"       =>  "%{metadata_product_name}"
      "event1.idm.read_only_udm.metadata.product_version"    =>  "%{metadata_product_version}"
      "event1.idm.read_only_udm.metadata.product_event_type" =>  "%{metadata_product_event_type}"
      "event1.idm.read_only_udm.metadata.product_log_id"     =>  "%{metadata_product_log_id}"
      "event1.idm.read_only_udm.metadata.description"        =>  "%{metadata_description}"
      "event1.idm.read_only_udm.metadata.event_type"         =>  "%{metadata_event_type}"
    }
  }

  # Set the UDM > auth fields
  mutate {
    replace => {
      "event1.idm.read_only_udm.extensions.auth.type"        => "%{auth_type}"
    }
    merge => {
      "event1.idm.read_only_udm.extensions.auth.mechanism"   => "auth_mechanism"
    }
  }

  # Set the UDM > principal fields
  mutate {
    merge => {
      "event1.idm.read_only_udm.principal.ip"                => "principal_ip"
    }
  }

  # Set the UDM > target fields
  mutate {
    replace => {
      "event1.idm.read_only_udm.target.user.userid"             =>  "%{target_user_userid}"
      "event1.idm.read_only_udm.target.user.user_display_name"  =>  "%{target_user_user_display_name}"
      "event1.idm.read_only_udm.target.application"             =>  "%{target_application}"
    }
  }

  # Set the UDM > security_results fields
  mutate {
    merge => {
      "security_result.action" => "securityResult_action"
    }
  }

  # Set the security result
  mutate {
    merge => {
      "event1.idm.read_only_udm.security_result" => "security_result"
    }
  }

 # ------------ Output the event  --------------
  mutate {
    merge => {
      "@output" => "event1"
    }
  }

}

Unstrukturierten Text mit einer Grok-Funktion parsen

Wenn Sie mit einer Grok-Funktion Werte aus unstrukturiertem Text extrahieren, vordefinierte Grok-Muster und Anweisungen für reguläre Ausdrücke verwenden. Grok-Muster damit der Code leichter zu lesen ist. Wenn der reguläre Ausdruck keine Kurzschreibweise enthält Zeichen (z. B. \w oder \s) können Sie die Anweisung direkt kopieren und einfügen. in den Parsercode ein.

Da Grok-Muster eine zusätzliche Abstraktionsebene in der Anweisung darstellen, können sie die Fehlerbehebung bei einem Fehler komplexer. Hier ein Beispiel Grok-Funktion, die sowohl vordefinierte Grok-Muster als auch reguläre Ausdrücke enthält.

grok {
  match => {
    "message" => [
      "%{NUMBER:when}\\s+\\d+\\s%{SYSLOGHOST:srcip} %{WORD:action}\\/%{NUMBER:returnCode} %{NUMBER:size} %{WORD:method} (?P<url>\\S+) (?P<username>.*?) %{WORD}\\/(?P<tgtip>\\S+).*"
    ]
  }
}

Eine Extraktionsanweisung ohne Grok-Muster kann leistungsstärker sein. Für dass im folgenden Beispiel weniger als die Hälfte der Verarbeitungsschritte für eine Übereinstimmung erforderlich ist. Bei einer Logquelle mit potenziell hohem Volumen ist dies eine wichtige Überlegung.

Unterschiede zwischen regulären RE2- und PCRE-Ausdrücken verstehen

Google Security Operations-Parser verwenden RE2 als reguläre Ausdrücke. Wenn Sie mit der PCRE-Syntax vertraut sind, Unterschiede wahrnehmen. Hier ein Beispiel:

Das ist eine PCRE-Anweisung: (?<_custom_field>\w+)\s

Im Folgenden finden Sie eine RE2-Anweisung für den Parsercode: (?P<_custom_field>\\w+)\\s

Achten Sie darauf, die Escape-Zeichen zu maskieren.

Google Security Operations speichert eingehende Logrohdaten im JSON-codierten Format. Damit möchten wir Zeichenzeichenfolgen, bei denen es sich offenbar um Abkürzungen für reguläre Ausdrücke handelt als literaler String interpretiert. Beispiel: \t wird als anstelle eines Tabulatorzeichens.

Das folgende Beispiel zeigt ein Original-Rohlog und das JSON-codierte Format-Log. Beachten Sie das Escape-Zeichen, das vor jedem umgekehrten Schrägstrich hinzugefügt wird. rund um den Begriff entry.

Hier sehen Sie das ursprüngliche Rohlog:

field=\entry\

Im Folgenden sehen Sie das Log, das in das JSON-codierte Format konvertiert wurde:

field=\\entry\\

Bei Verwendung eines regulären Ausdrucks im Parsercode müssen Sie ein zusätzliches Escapezeichen hinzufügen. Zeichen, wenn Sie nur den Wert extrahieren möchten. Um einen umgekehrten Schrägstrich in des ursprünglichen Rohprotokolls in der Extraktionsanweisung vier umgekehrte Schrägstriche.

Im Folgenden finden Sie einen regulären Ausdruck für Parsercode:

^field=\\\\(?P<_value>.*)\\\\$

Im Folgenden sehen Sie das generierte Ergebnis. Die benannte Gruppe _value speichert den Begriff entry:

"_value": "entry"

Wenn Sie eine standardmäßige Anweisung für einen regulären Ausdruck in den Parsercode verschieben, maskieren Sie Kurzzeichen für reguläre Ausdrücke in der Extraktionsanweisung. Ändern Sie beispielsweise \s in \\s.

Lassen Sie Sonderzeichen für reguläre Ausdrücke unverändert, wenn sie im Feld Extraktionsanweisung. Beispielsweise bleibt \\ unverändert als \\.

Im Folgenden sehen Sie einen standardmäßigen regulären Ausdruck:

^.*?\\\"(?P<_user>[^\\]+)\\\"\s(?:(logged\son|logged\soff))\s.*?\\\"(?P<_device>[^\\]+)\\\"\.$

Der folgende reguläre Ausdruck wird so geändert, dass er im Parsercode funktioniert.

^.*?\\\"(?P<_user>[^\\\\]+)\\\"\\s(?:(logged\\son|logged\\soff))\\s.*?\\\"(?P<_device>[^\\\\]+)\\\"\\.$

In der folgenden Tabelle wird zusammengefasst, wann ein regulärer regulärer Ausdruck Folgendes enthalten muss: zusätzliche Escape-Zeichen ein, bevor sie in den Parsercode aufgenommen werden.

Regulärer Ausdruck Geänderter regulärer Ausdruck für Parsercode Beschreibung der Änderung
\s
\\s
Kürzel müssen maskiert werden.
\.
\\.
Reservierte Zeichen müssen maskiert werden.
\\"
\\\"
Reservierte Zeichen müssen maskiert werden.
\]
\\]
Reservierte Zeichen müssen maskiert werden.
\|
\\|
Reservierte Zeichen müssen maskiert werden.
[^\\]+
[^\\\\]+
Sonderzeichen in einer Zeichenklassengruppe müssen ist entkommen.
\\\\
\\\\
Sonderzeichen außerhalb einer Zeichenklassengruppe oder Für Kurzzeichen ist kein zusätzliches Escape-Zeichen erforderlich.

Reguläre Ausdrücke müssen eine benannte Erfassungsgruppe enthalten

Ein regulärer Ausdruck wie "^.*$" ist eine gültige RE2-Syntax. Im Parser Code schlägt er mit dem folgenden Fehler fehl:

"ParseLogEntry failed: pipeline failed: filter grok (0) failed: failed to parse data with all match
patterns"

Sie müssen dem Ausdruck eine gültige Erfassungsgruppe hinzufügen. Bei Verwendung von Grok enthalten diese standardmäßig eine benannte Erfassungsgruppe. Bei Verwendung der regulären Ausdrucksüberschreibungen enthalten, müssen Sie eine benannte Gruppe einfügen.

Hier sehen Sie ein Beispiel für einen regulären Ausdruck im Parsercode:

"^(?P<_catchall>.*$)"

Im Folgenden finden Sie das Ergebnis mit dem Text, der der benannten Gruppe _catchall zugewiesen ist.

"_catchall": "User \"BOB\" logged on to workstation \"DESKTOP-01\"."

Verwenden Sie eine universelle benannte Gruppe, um mit dem Erstellen des Ausdrucks zu beginnen

Beginnen Sie beim Erstellen einer Extraktionsanweisung mit einem Ausdruck, der die mehr als Sie möchten. Erweitern Sie dann den Ausdruck um ein Feld nach dem anderen.

Im folgenden Beispiel wird zuerst eine benannte Gruppe (_catchall) verwendet, die mit der gesamten Nachricht. Anschließend wird der Ausdruck in Schritten erstellt, indem er zusätzliche Teile des Textes. Bei jedem Schritt hat die benannte Gruppe _catchall enthält weniger vom Originaltext. Fahren Sie fort und iterieren Sie Schritt für Schritt, mit der Nachricht abgleichen, bis Sie die benannte Gruppe _catchall nicht mehr benötigen.

Schritt Regulärer Ausdruck im Parsercode Ausgabe der benannten Erfassungsgruppe _catchall
1
"^(?P<_catchall>.*$)"
User \"BOB\" logged on to workstation \"DESKTOP-01\".
2
^User\s\\\"(?P<_catchall>.*$)
BOB\" logged on to workstation \"DESKTOP-01\".
3
^User\s\\\"(?P<_user>.*?)\\\"\s(?P<_catchall>.*$)
logged on to workstation \"DESKTOP-01\".
Fahren Sie fort, bis der Ausdruck mit der gesamten Textzeichenfolge übereinstimmt.

Escapezeichen für Kurzzeichen im regulären Ausdruck

Denken Sie daran, Escape-Zeichen für reguläre Ausdrücke zu maskieren, wenn Sie die Methode Ausdruck im Parser-Code. Es folgt ein Beispiel für eine Textzeichenfolge und den Standardausdruck mit regulärem Ausdruck zum Extrahiert das erste Wort, This.

  This is a sample log.

Mit dem folgenden regulären regulären Ausdruck wird das erste Wort, This, extrahiert. Wenn Sie diesen Ausdruck jedoch im Parsercode ausführen, fehlt im Ergebnis der Buchstabe s

Regulärer Ausdruck (Standardausdruck) Ausgabe der benannten Erfassungsgruppe _firstWord
"^(?P<_firstWord>[^\s]+)\s.*$" "_firstWord": "Thi",

Das liegt daran, dass reguläre Ausdrücke im Parsercode ein zusätzliches Escapezeichen erfordern. -Zeichen zu Kurzzeichen hinzugefügt. Im vorherigen Beispiel muss \s in \\s geändert werden.

Überarbeiteter regulärer Ausdruck für Parsercode Ausgabe der benannten Erfassungsgruppe _firstWord
"^(?P<_firstWord>[^\\s]+)\\s.*$" "_firstWord": "This",

Dies gilt nur für Kurzzeichen wie \s, \r und \t. Andere Zeichen wie `` müssen nicht weiter mit Escapezeichen versehen werden.

Vollständiges Beispiel

In diesem Abschnitt werden die vorherigen Regeln als End-to-End-Beispiel beschrieben. Hier ist ein unstrukturierte Textzeichenfolge und der reguläre reguläre Ausdruck, der zum Parsen geschrieben wurde die Zeichenfolge. Schließlich enthält sie den modifizierten regulären Ausdruck, der im Parser-Code enthalten.

Im Folgenden sehen Sie die ursprüngliche Textzeichenfolge.

User "BOB" logged on to workstation "DESKTOP-01".

Im Folgenden finden Sie einen regulären regulären Ausdruck für RE2, der den Textstring parst.

^.*?\\\"(?P<_user>[^\\]+)\\\"\s(?:(logged\son|logged\soff))\s.*?\\\"(?P<_device>[^\\]+)\\\"\.$

Mit diesem Ausdruck werden die folgenden Felder extrahiert.

Übereinstimmungsgruppe Zeichenposition Textstring
Vollständige Übereinstimmung 0-53
User \"BOB\" logged on to workstation \"DESKTOP-01\".
Gruppe „_user“ 7-10
BOB
Gruppe 2: 13-22
logged on
Gruppe „_device“ 40-50
DESKTOP-01

Dies ist der geänderte Ausdruck. Der reguläre reguläre Ausdruck „RE2“ wurde geändert, damit er im Parsercode funktioniert.

^.*?\\\"(?P<_user>[^\\\\]+)\\\"\\s(?:(logged\\son|logged\\soff))\\s.*?\\\"(?P<_device>[^\\\\]+)\\\"\\.$