Tips dan pemecahan masalah saat menulis parser

Didukung di:

Dokumen ini menjelaskan masalah yang mungkin Anda alami saat menulis kode parser.

Saat menulis kode parser, Anda mungkin mengalami error saat menguraikan instruksi yang tidak berfungsi seperti yang diharapkan. Situasi yang dapat menimbulkan error meliputi hal berikut:

  • Pola Grok gagal
  • Operasi rename atau replace gagal
  • Error sintaksis dalam kode parser

Praktik umum dalam kode parser

Bagian berikut menjelaskan praktik terbaik, tips, dan solusi untuk membantu memecahkan masalah.

Hindari penggunaan titik atau tanda hubung dalam nama variabel

Penggunaan tanda hubung dan titik dalam nama variabel dapat menyebabkan perilaku yang tidak terduga, terutama saat melakukan operasi merge untuk menyimpan nilai di kolom UDM. Anda juga mungkin mengalami masalah parsing yang terputus-putus.

Misalnya, jangan gunakan nama variabel berikut:

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

Sebagai gantinya, gunakan nama variabel berikut: my_variable_result.

Jangan gunakan istilah dengan makna khusus sebagai nama variabel

Kata-kata tertentu, seperti event dan timestamp, dapat memiliki arti khusus dalam kode parser.

String event sering digunakan untuk merepresentasikan satu rekaman UDM dan digunakan dalam pernyataan @output. Jika pesan log menyertakan kolom bernama event, atau jika Anda menentukan variabel perantara bernama event, dan kode parser menggunakan kata event dalam pernyataan @output, Anda akan mendapatkan pesan error tentang konflik nama.

Ganti nama variabel perantara menjadi nama lain, atau gunakan istilah event1 sebagai awalan dalam nama kolom UDM dan dalam pernyataan @output.

Kata timestamp mewakili stempel waktu yang dibuat dari log mentah asli. Nilai yang ditetapkan dalam variabel perantara ini disimpan ke kolom UDM metadata.event_timestamp. Istilah @timestamp menunjukkan tanggal dan waktu log mentah diuraikan untuk membuat rekaman UDM.

Contoh berikut menetapkan kolom UDM metadata.event_timestamp ke tanggal dan waktu log mentah diuraikan.

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

Contoh berikut menetapkan kolom UDM metadata.event_timestamp ke tanggal dan waktu yang diekstrak dari log mentah asli dan disimpan dalam variabel perantara when.

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

Jangan gunakan istilah berikut sebagai variabel:

  • collectiontimestamp
  • createtimestamp
  • event
  • filename
  • pesan
  • namespace
  • output
  • onerrorcount
  • timestamp
  • zona waktu

Menyimpan setiap nilai data di kolom UDM terpisah

Jangan menyimpan beberapa kolom dalam satu kolom UDM dengan menggabungkannya menggunakan pembatas. Berikut adalah contohnya:

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

Sebagai gantinya, simpan setiap nilai di kolom UDM terpisah.

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

Gunakan spasi, bukan tab dalam kode

Jangan gunakan tab dalam kode parser. Gunakan hanya spasi dan indentasi 2 spasi sekaligus.

Jangan melakukan beberapa tindakan penggabungan dalam satu operasi

Jika Anda menggabungkan beberapa kolom dalam satu operasi, hal ini dapat menyebabkan hasil yang tidak konsisten. Sebagai gantinya, tempatkan pernyataan merge ke dalam operasi terpisah.

Misalnya, ganti contoh berikut:

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

Dengan ini:

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

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

Memilih ekspresi bersyarat if versus if else

Jika nilai kondisional yang Anda uji hanya dapat memiliki satu kecocokan, maka gunakan pernyataan kondisional if else. Pendekatan ini sedikit lebih efisien. Namun, jika Anda memiliki skenario di mana nilai yang diuji dapat cocok lebih dari sekali, gunakan beberapa pernyataan if yang berbeda dan urutkan pernyataan dari kasus yang paling umum hingga kasus yang paling spesifik.

Pilih sekumpulan file log yang representatif untuk menguji perubahan parser

Praktik terbaiknya adalah menguji kode parser menggunakan sampel log mentah dengan berbagai format. Dengan begitu, Anda dapat menemukan log unik atau kasus ekstrem yang mungkin perlu ditangani oleh parser.

Menambahkan komentar deskriptif ke kode parser

Tambahkan komentar ke kode parser yang menjelaskan mengapa pernyataan tersebut penting, bukan apa yang dilakukan pernyataan tersebut. Komentar ini membantu siapa pun yang memelihara parser untuk mengikuti alurnya. Berikut adalah contohnya:

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

Lakukan inisialisasi variabel perantara lebih awal

Sebelum mengekstrak nilai dari log mentah asli, lakukan inisialisasi variabel perantara yang akan digunakan untuk menyimpan nilai pengujian.

Hal ini mencegah error ditampilkan yang menunjukkan bahwa variabel perantara tidak ada.

Pernyataan berikut menetapkan nilai dalam variabel product ke kolom UDM metadata.product_name.

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

Jika variabel product tidak ada, Anda akan mendapatkan error berikut:

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

Anda dapat menambahkan pernyataan on_error untuk menangkap error. Berikut adalah contohnya:

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

Pernyataan contoh sebelumnya berhasil menangkap error parsing ke dalam variabel perantara boolean, yang disebut _error_does_not_exist. Hal ini tidak memungkinkan Anda menggunakan variabel product dalam pernyataan bersyarat, misalnya if. Berikut adalah contohnya:

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

Contoh sebelumnya menampilkan error berikut karena klausa bersyarat if tidak mendukung pernyataan on_error:

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

Untuk mengatasinya, tambahkan blok pernyataan terpisah yang menginisialisasi variabel perantara sebelum menjalankan pernyataan filter ekstraksi (json, csv, xml, kv, atau grok). Berikut adalah contohnya.

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

Cuplikan kode parser yang diperbarui menangani beberapa skenario menggunakan pernyataan kondisional untuk memeriksa apakah kolom ada. Selain itu, pernyataan on_error menangani error yang mungkin terjadi.

Mengonversi SHA-256 ke base64

Contoh berikut mengekstrak nilai SHA-256, mengenkodenya dalam base64, mengonversi data yang dienkode menjadi string heksadesimal, lalu mengganti kolom tertentu dengan nilai yang diekstrak dan diproses.

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

Menangani error dalam pernyataan parser

Bukan hal yang aneh jika log masuk memiliki format log yang tidak terduga atau memiliki data yang diformat dengan buruk.

Anda dapat membuat parser untuk menangani error ini. Praktik terbaik adalah menambahkan handler on_errorke filter ekstraksi, lalu menguji variabel perantara sebelum melanjutkan ke segmen logika parser berikutnya.

Contoh berikut menggunakan filter ekstraksi json dengan pernyataan on_error untuk menyetel variabel boolean _not_json. Jika _not_json disetel ke true, berarti entri log yang masuk tidak dalam format JSON yang valid dan entri log tidak berhasil diuraikan. Jika variabel _not_json adalah false, entri log yang masuk dalam format JSON yang valid.

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

Anda juga dapat menguji apakah kolom memiliki format yang benar. Contoh berikut memeriksa apakah _not_json disetel ke true, yang menunjukkan bahwa log tidak dalam format yang diharapkan.

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

Hal ini memastikan bahwa penguraian tidak akan gagal jika log dimasukkan dengan format yang salah untuk jenis log yang ditentukan.

Gunakan filter drop dengan variabel tag sehingga kondisi dicatat dalam tabel metrik Penyerapan di BigQuery.

  • TAG_UNSUPPORTED
  • TAG_MALFORMED_ENCODING
  • TAG_MALFORMED_MESSAGE
  • TAG_NO_SECURITY_VALUE

Filter drop menghentikan parser memproses log mentah, menormalisasi kolom, dan membuat rekaman UDM. Log mentah asli masih di-ingest ke Google Security Operations dan dapat ditelusuri menggunakan penelusuran log mentah di Google SecOps.

Nilai yang diteruskan ke variabel tag disimpan di kolom drop_reason_code' dalam tabel Metrik penyerapan. Anda dapat menjalankan kueri ad hoc terhadap tabel yang mirip dengan berikut:

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

Memecahkan masalah error validasi

Saat membuat parser, Anda mungkin mengalami error terkait validasi, misalnya, kolom wajib diisi tidak ditetapkan dalam rekaman UDM. Error mungkin terlihat seperti berikut:

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

Kode parser berhasil dieksekusi, tetapi rekaman UDM yang dihasilkan tidak mencakup semua kolom UDM yang diperlukan sebagaimana ditentukan oleh set nilai yang ditetapkan ke metadata.event_type. Berikut contoh tambahan yang dapat menyebabkan error ini:

  • Jika metadata.event_type adalah USER_LOGIN dan kolom UDM target.user value tidak ditetapkan.
  • Jika metadata.event_type adalah NETWORK_CONNECTION dan kolom target.hostnameUDM tidak ditetapkan.

Untuk mengetahui informasi selengkapnya tentang kolom UDM metadata.event_type dan kolom wajib diisi, lihat panduan penggunaan UDM.

Salah satu opsi untuk memecahkan masalah jenis error ini adalah dengan memulai menyetel nilai statis ke kolom UDM. Setelah Anda menentukan semua kolom UDM yang diperlukan, periksa log mentah asli untuk melihat nilai mana yang akan diuraikan dan disimpan ke dalam data UDM. Jika log mentah asli tidak berisi kolom tertentu, Anda mungkin perlu menetapkan nilai default.

Berikut adalah contoh template, khusus untuk jenis peristiwa USER_LOGIN, yang mengilustrasikan pendekatan ini.

Perhatikan berikut ini:

  • Template menginisialisasi variabel perantara dan menetapkan setiap variabel ke string statis.
  • Kode di bagian Penetapan Kolom menetapkan nilai dalam variabel perantara ke kolom UDM.

Anda dapat memperluas kode ini dengan menambahkan variabel perantara dan kolom UDM tambahan. Setelah Anda mengidentifikasi semua kolom UDM yang harus diisi, lakukan hal berikut:

  • Di bagian Konfigurasi Input, tambahkan kode yang mengekstrak kolom dari log mentah asli dan menetapkan nilai ke variabel perantara.

  • Di bagian Ekstraksi Tanggal, tambahkan kode yang mengekstrak stempel waktu peristiwa dari log mentah asli, mengubahnya, dan menyetelnya ke variabel perantara.

  • Jika perlu, ganti nilai yang diinisialisasi yang ditetapkan di setiap variabel perantara dengan string kosong.

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

}

Mengurai teks tidak terstruktur menggunakan fungsi Grok

Saat menggunakan fungsi Grok untuk mengekstrak nilai dari teks tidak terstruktur, Anda dapat menggunakan pola Grok yang telah ditentukan sebelumnya dan pernyataan ekspresi reguler. Pola Grok membuat kode lebih mudah dibaca. Jika ekspresi reguler tidak menyertakan karakter singkat (seperti \w, \s), Anda dapat menyalin dan menempelkan pernyataan langsung ke dalam kode parser.

Karena pola Grok adalah lapisan abstraksi tambahan dalam pernyataan, pola ini dapat membuat pemecahan masalah menjadi lebih rumit saat Anda mengalami error. Berikut adalah contoh fungsi Grok yang berisi pola Grok yang telah ditentukan sebelumnya dan ekspresi reguler.

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+).*"
    ]
  }
}

Pernyataan ekstraksi tanpa pola Grok mungkin memiliki performa yang lebih baik. Misalnya, contoh berikut memerlukan kurang dari setengah langkah pemrosesan untuk mencocokkan. Untuk sumber log yang berpotensi memiliki volume tinggi, hal ini merupakan pertimbangan penting.

Memahami perbedaan antara ekspresi reguler RE2 dan PCRE

Parser Google SecOps menggunakan RE2 sebagai mesin ekspresi reguler. Jika Anda sudah terbiasa dengan sintaksis PCRE, Anda mungkin melihat perbedaan. Berikut adalah salah satu contohnya:

Berikut adalah pernyataan PCRE: (?<_custom_field>\w+)\s

Berikut adalah pernyataan RE2 untuk kode parser: (?P<_custom_field>\\w+)\\s

Pastikan untuk meng-escape karakter escape

Google SecOps menyimpan data log mentah yang masuk dalam format yang dienkode JSON. Hal ini dilakukan untuk memastikan bahwa string karakter yang tampak seperti singkatan ekspresi reguler ditafsirkan sebagai string literal. Misalnya, \t ditafsirkan sebagai string literal, bukan karakter tab.

Contoh berikut adalah log mentah asli dan log format yang dienkode JSON. Perhatikan karakter escape yang ditambahkan di depan setiap karakter garis miring terbalik yang mengapit istilah entry.

Berikut adalah log mentah asli:

field=\entry\

Berikut adalah log yang dikonversi ke format yang dienkode JSON:

field=\\entry\\

Saat menggunakan ekspresi reguler dalam kode parser, Anda harus menambahkan karakter escape tambahan jika ingin mengekstrak hanya nilai. Untuk mencocokkan garis miring terbalik dalam log mentah asli, gunakan empat garis miring terbalik dalam pernyataan ekstraksi.

Berikut adalah ekspresi reguler untuk kode parser:

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

Berikut adalah hasil yang dihasilkan. Grup bernama _value menyimpan istilah entry:

"_value": "entry"

Saat memindahkan pernyataan ekspresi reguler standar ke dalam kode parser, kecualikan karakter singkat ekspresi reguler dalam pernyataan ekstraksi. Misalnya, ubah \s menjadi \\s.

Biarkan karakter khusus ekspresi reguler tidak berubah saat di-escape ganda dalam pernyataan ekstraksi. Misalnya, \\ tetap tidak berubah sebagai \\.

Berikut adalah ekspresi reguler standar:

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

Ekspresi reguler berikut diubah agar berfungsi dalam kode parser.

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

Tabel berikut merangkum kapan ekspresi reguler standar harus menyertakan karakter escape tambahan sebelum menyertakannya dalam kode parser.

Ekspresi reguler Ekspresi reguler yang diubah untuk kode parser Deskripsi perubahan
\s
\\s
Karakter singkatan harus di-escape.
\.
\\.
Karakter yang dicadangkan harus di-escape.
\\"
\\\"
Karakter yang dicadangkan harus di-escape.
\]
\\]
Karakter yang dicadangkan harus di-escape.
\|
\\|
Karakter yang dicadangkan harus di-escape.
[^\\]+
[^\\\\]+
Karakter khusus dalam grup kelas karakter harus di-escape.
\\\\
\\\\
Karakter khusus di luar grup class karakter atau karakter singkat tidak memerlukan escape tambahan.

Ekspresi reguler harus menyertakan grup tangkapan bernama

Ekspresi reguler, seperti "^.*$", adalah sintaksis RE2 yang valid. Namun, dalam kode parser, kode tersebut gagal dengan error berikut:

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

Anda harus menambahkan grup tangkapan yang valid ke ekspresi. Jika Anda menggunakan pola Grok, pola ini menyertakan grup pengambilan bernama secara default. Saat menggunakan penggantian ekspresi reguler, pastikan untuk menyertakan grup bernama.

Berikut adalah contoh ekspresi reguler dalam kode parser:

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

Berikut adalah hasilnya, yang menampilkan teks yang ditetapkan ke grup bernama _catchall.

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

Gunakan grup bernama catchall untuk memulai saat Anda membuat ekspresi

Saat membuat pernyataan ekstraksi, mulailah dengan ekspresi yang menangkap lebih banyak dari yang Anda inginkan. Kemudian, luaskan ekspresi satu kolom dalam satu waktu.

Contoh berikut dimulai dengan menggunakan grup bernama (_catchall) yang cocok dengan seluruh pesan. Kemudian, ekspresi ini dibuat secara bertahap dengan mencocokkan bagian tambahan dari teks. Dengan setiap langkah, grup bernama _catchall berisi lebih sedikit teks asli. Lanjutkan dan ulangi satu langkah dalam satu waktu untuk mencocokkan pesan hingga Anda tidak lagi memerlukan grup bernama _catchall.

Langkah Regular expression dalam kode parser Output grup pengambilan bernama _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\".
Lanjutkan hingga ekspresi cocok dengan seluruh string teks.

Meng-escape karakter singkat dalam ekspresi reguler

Jangan lupa untuk memisahkan karakter singkat ekspresi reguler saat menggunakan ekspresi dalam kode parser. Berikut adalah contoh string teks dan ekspresi reguler standar yang mengekstrak kata pertama, This.

  This is a sample log.

Ekspresi reguler standar berikut mengekstrak kata pertama, This. Namun, saat Anda menjalankan ekspresi ini dalam kode parser, hasilnya tidak menyertakan huruf s.

Ekspresi reguler standar Output grup pengambilan bernama _firstWord
"^(?P<_firstWord>[^\s]+)\s.*$" "_firstWord": "Thi",

Hal ini karena ekspresi reguler dalam kode parser memerlukan karakter escape tambahan yang ditambahkan ke karakter singkat. Dalam contoh sebelumnya, \s harus diubah menjadi \\s.

Revisi ekspresi reguler untuk kode parser Output grup pengambilan bernama _firstWord
"^(?P<_firstWord>[^\\s]+)\\s.*$" "_firstWord": "This",

Hal ini hanya berlaku untuk karakter singkat, seperti \s, \r, dan \t. Karakter lain, seperti ``, tidak perlu di-escape lebih lanjut.

Contoh lengkap

Bagian ini menjelaskan aturan sebelumnya sebagai contoh end-to-end. Berikut adalah string teks tidak terstruktur, dan ekspresi reguler standar yang ditulis untuk mengurai string. Terakhir, ini mencakup ekspresi reguler yang diubah yang berfungsi dalam kode parser.

Berikut adalah string teks asli.

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

Berikut adalah ekspresi reguler RE2 standar yang mengurai string teks.

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

Ekspresi ini mengekstrak kolom berikut.

Grup kecocokan Posisi karakter String teks
Kecocokan penuh 0-53
User \"BOB\" logged on to workstation \"DESKTOP-01\".
Grup `_user` 7-10
BOB
Grup 2. 13-22
logged on
Grup `_device` 40-50
DESKTOP-01

Ini adalah ekspresi yang diubah. Ekspresi reguler RE2 standar diubah agar berfungsi dalam kode parser.

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

Perlu bantuan lain? Dapatkan jawaban dari anggota Komunitas dan profesional Google SecOps.