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 petunjuk penguraian tidak berfungsi seperti yang diharapkan. Situasi yang mungkin menghasilkan 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, sering kali saat melakukan operasi merge untuk menyimpan nilai di kolom UDM. Anda juga mungkin mengalami masalah penguraian 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 tertentu, seperti event dan timestamp, dapat memiliki arti khusus dalam kode parser.

String event sering digunakan untuk mewakili satu kumpulan data UDM dan digunakan dalam pernyataan @output. Jika pesan log menyertakan kolom yang disebut event, atau jika Anda menentukan variabel perantara yang disebut 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 mewakili tanggal dan waktu log mentah diuraikan untuk membuat data 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 dengan pemisah. 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}"

Menggunakan spasi, bukan tab, dalam kode

Jangan gunakan tab dalam kode parser. Hanya gunakan 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, gunakan pernyataan kondisional if else. Pendekatan ini sedikit lebih efisien. Namun, jika Anda memiliki skenario saat nilai yang diuji dapat cocok lebih dari sekali, gunakan beberapa pernyataan if yang berbeda dan urutkan pernyataan dari kasus yang paling umum ke kasus yang paling spesifik.

Memilih kumpulan file log yang representatif untuk menguji perubahan parser

Praktik terbaiknya adalah menguji kode parser menggunakan contoh log mentah dengan berbagai format. Hal ini memungkinkan Anda 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 membantu siapa pun yang mengelola parser untuk mengikuti alur. 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}"
    }
  }
}

Melakukan inisialisasi variabel perantara lebih awal

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

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

Contoh pernyataan sebelumnya berhasil menangkap error penguraian 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 mengatasi hal ini, 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 tersebut 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

Log yang masuk sering kali memiliki format log yang tidak terduga atau data yang tidak diformat dengan benar.

Anda dapat mem-build parser untuk menangani error ini. Praktik terbaiknya adalah menambahkan pengendali on_error ke filter ekstraksi, lalu menguji variabel perantara sebelum melanjutkan ke segmen logika parser berikutnya.

Contoh berikut menggunakan filter ekstraksi json dengan pernyataan on_error untuk menetapkan variabel boolean _not_json. Jika _not_json ditetapkan ke true, artinya 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 ditetapkan 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 gagal jika log diserap dengan format yang salah untuk jenis log yang ditentukan.

Gunakan filter drop dengan variabel tag sehingga kondisinya dicatat dalam tabel Metrik proses transfer 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 data UDM. Log mentah asli masih diserap ke Google Security Operations dan dapat ditelusuri menggunakan penelusuran log mentah di Google Security Operations.

Nilai yang diteruskan ke variabel tag disimpan di kolom drop_reason_code' di tabel Metrik proses transfer. 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 mem-build parser, Anda mungkin mengalami error yang terkait dengan validasi, misalnya, kolom wajib diisi tidak ditetapkan dalam data UDM. Error ini mungkin terlihat mirip dengan 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 data UDM yang dihasilkan tidak menyertakan semua kolom UDM yang diperlukan seperti yang ditentukan oleh 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 UDM target.hostname tidak ditetapkan.

Untuk informasi selengkapnya tentang kolom UDM metadata.event_type dan kolom yang diperlukan, lihat panduan penggunaan UDM.

Salah satu opsi untuk memecahkan masalah jenis error ini adalah dengan memulai dengan menetapkan 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 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 menggambarkan pendekatan ini.

Perhatikan berikut ini:

  • Template ini melakukan inisialisasi 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 Input Configuration, tambahkan kode yang mengekstrak kolom dari log mentah asli dan menetapkan nilai ke variabel perantara.

  • Di bagian Date Extract, tambahkan kode yang mengekstrak stempel waktu peristiwa dari log mentah asli, mengubahnya, dan menetapkannya ke variabel perantara.

  • Sesuai kebutuhan, ganti nilai yang diinisialisasi yang ditetapkan di setiap variabel median menjadi 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 tersebut dapat membuat pemecahan masalah menjadi lebih kompleks saat Anda mengalami error. Berikut adalah contoh fungsi Grok yang berisi pola Grok dan ekspresi reguler yang telah ditentukan sebelumnya.

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 dicocokkan. Untuk sumber log yang berpotensi memiliki volume tinggi, ini adalah pertimbangan yang penting.

Memahami perbedaan antara ekspresi reguler RE2 dan PCRE

Parser Google Security Operations menggunakan RE2 sebagai mesin ekspresi reguler. Jika 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 Security Operations menyimpan data log mentah yang masuk dalam format yang dienkode JSON. Hal ini untuk memastikan bahwa string karakter yang tampak seperti singkatan ekspresi reguler diinterpretasikan 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 mengelilingi 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 hanya ingin mengekstrak 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 kode parser, hindari karakter singkatan ekspresi reguler dalam pernyataan ekstraksi. Misalnya, ubah \s menjadi \\s.

Jangan ubah karakter khusus ekspresi reguler saat melakukan 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.

Regular expression Ekspresi reguler yang dimodifikasi 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 class karakter harus di-escape.
\\\\
\\\\
Karakter khusus di luar grup class karakter atau karakter singkatan tidak memerlukan escape tambahan.

Ekspresi reguler harus menyertakan grup tangkapan yang dinamai

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 akan menyertakan grup tangkapan 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 generik untuk memulai saat Anda membuat ekspresi

Saat membuat pernyataan ekstraksi, mulailah dengan ekspresi yang menangkap lebih 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 akan dibuat secara bertahap dengan mencocokkan bagian tambahan teks. Dengan setiap langkah, grup bernama _catchall akan berisi lebih sedikit teks asli. Lanjutkan dan lakukan iterasi satu langkah demi satu langkah untuk mencocokkan pesan hingga Anda tidak lagi memerlukan grup bernama _catchall.

Langkah Ekspresi reguler 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 singkatan dalam ekspresi reguler

Ingatlah untuk meng-escape karakter singkatan 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 memiliki 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 singkatan. Pada contoh sebelumnya, \s harus diubah menjadi \\s.

Regular expression yang direvisi untuk kode parser Output grup pengambilan bernama _firstWord
"^(?P<_firstWord>[^\\s]+)\\s.*$" "_firstWord": "This",

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

Contoh lengkap

Bagian ini menjelaskan aturan sebelumnya sebagai contoh menyeluruh. Berikut adalah string teks yang tidak terstruktur, dan ekspresi reguler standar yang ditulis untuk mengurai string. Terakhir, ini mencakup ekspresi reguler yang dimodifikasi 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 pencocokan 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 dimodifikasi 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.