Tipps und Fehlerbehebung beim Schreiben von Parsern

Unterstützt in:

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, oft 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. Ein in dieser Zwischenvariablen festgelegter Wert wird im UDM-Feld metadata.event_timestamp gespeichert. 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:

  • collectiontimestamp
  • 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.

Führen Sie nicht mehrere Zusammenführungsaktionen in einem einzigen Vorgang aus.

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 Folgendes:

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"
  }
}

if- oder if else-Bedingte Ausdrücke auswählen

Wenn der getestete bedingte Wert immer nur eine Übereinstimmung haben kann, verwenden Sie die bedingte Anweisung if else. 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

Es empfiehlt sich, Parsercode mit Rohprotokollbeispielen in einer Vielzahl von Formaten zu testen. So können Sie eindeutige Protokolle oder Grenzfälle finden, die der Parser möglicherweise verarbeiten muss.

Dem Parsercode beschreibende Kommentare 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.

In der folgenden Anweisung wird der Wert in der Variablen product dem UDM-Feld metadata.product_name zugewiesen.

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 zu erfassen. 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 wird empfohlen, dem Extraktionsfilter on_error-Handler hinzuzufügen und dann die Zwischenvariable zu testen, bevor mit dem nächsten Segment der Parserlogik fortgefahren wird.

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 wird geprüft, ob _not_json auf true gesetzt ist, was bedeutet, dass das Protokoll nicht im erwarteten Format vorliegt.

 # 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" }
    }
  }

So wird verhindert, dass das Parsen fehlschlägt, wenn Protokolle in einem falschen Format für den angegebenen Protokolltyp aufgenommen werden.

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 und das UDM-Feld target.hostname nicht festgelegt ist.

Weitere Informationen zum UDM-Feld metadata.event_type und zu den erforderlichen Feldern finden Sie im Leitfaden zur UDM-Nutzung.

Eine Möglichkeit zur Behebung dieses Fehlertyps besteht darin, zuerst statische Werte auf UDM festzulegen. . Nachdem Sie alle erforderlichen UDM-Felder definiert haben, überprüfen Sie das ursprüngliche Rohprotokoll, 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.

Im Folgenden finden Sie eine Beispielvorlage für einen USER_LOGIN-Ereignistyp, die diesen Ansatz veranschaulicht.

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. Im folgenden Beispiel wird eine Grok-Funktion mit vordefinierten Grok-Mustern und regulären Ausdrücken verwendet.

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. Im folgenden Beispiel werden beispielsweise weniger als die Hälfte der Verarbeitungsschritte für die Übereinstimmung benötigt. Bei einer Protokollquelle mit potenziell hohem Volumen ist dies ein wichtiger Aspekt.

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

Die Parser von Google Security Operations verwenden RE2 als reguläre Ausdrucks-Engine. Wenn Sie mit der PCRE-Syntax vertraut sind, werden Ihnen möglicherweise Unterschiede auffallen. Hier ein Beispiel:

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

Hier sehen 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, die wie Abkürzungen für reguläre Ausdrücke zu sein scheinen, 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, dass das Escape-Zeichen vor jedem umgekehrten Schrägstrich eingefü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.

Hier ist ein regulärer 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 reguläre Ausdrucks-Sonderzeichen unverändert, wenn sie in der Extraktionsbeschreibung doppelt maskiert sind. \\ bleibt beispielsweise unverändert als \\.

Hier ein Standard-regulärer 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 mit Escapezeichen versehen werden.
\\"
\\\"
Reservierte Zeichen müssen maskiert werden.
\]
\\]
Reservierte Zeichen müssen maskiert werden.
\|
\\|
Reservierte Zeichen müssen mit Escapezeichen versehen werden.
[^\\]+
[^\\\\]+
Sonderzeichen innerhalb einer Zeichenklassengruppe müssen maskiert werden.
\\\\
\\\\
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 sehen 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 wiederholen Sie die Schritte nacheinander, bis die Nachricht übereinstimmt. Die Gruppe mit dem Namen _catchall ist dann nicht mehr erforderlich.

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, reguläre Ausdruckskürzel zu maskieren, wenn Sie den Ausdruck im Parsercode verwenden. Es folgt ein Beispiel für eine Textzeichenfolge und den Standardausdruck mit regulärem Ausdruck, mit dem das erste Wort, This, extrahiert wird.

  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 sehen Sie einen unstrukturierten Textstring und den Standardregulären Ausdruck, der zum Parsen des Strings geschrieben wurde. 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 standardmäßigen RE2-regulären Ausdruck, der den Textstring analysiert.

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

Mit diesem Ausdruck werden die folgenden Felder extrahiert.

Abgleichsgruppe 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>[^\\\\]+)\\\"\\.$