Tips dan pemecahan masalah saat menulis parser
Dokumen ini menjelaskan masalah yang mungkin Anda temui 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:
- Pola
Grok
gagal - Operasi
rename
ataureplace
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 pada nama variabel dapat menyebabkan perilaku yang tidak terduga, sering kali saat melakukan operasi merge
untuk menyimpan nilai dalam kolom UDM. Anda mungkin juga 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 arti khusus sebagai nama variabel
Kata tertentu, seperti event
dan timestamp
, dapat memiliki arti khusus dalam kode parser.
String event
sering digunakan untuk mewakili satu 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 yang 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 saat log mentah diurai untuk membuat data UDM.
Contoh berikut menetapkan kolom UDM metadata.event_timestamp
ke tanggal dan waktu saat 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:
- stempel waktu koleksi
- buatstempel waktu
- event
- filename
- pesan
- namespace
- output
- onerrorcount
- timestamp
- zona waktu
Simpan setiap nilai data dalam 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}"
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 sedang Anda uji hanya dapat memiliki satu kecocokan, gunakan pernyataan kondisional if else
. Pendekatan ini sedikit lebih efisien. Namun, jika Anda memiliki skenario dengan nilai yang diuji dapat cocok lebih dari satu kali, gunakan beberapa pernyataan if
yang berbeda dan urutkan pernyataan tersebut dari kasus yang paling umum ke kasus yang paling spesifik.
Pilih kumpulan file log yang representatif untuk menguji perubahan parser
Praktik terbaiknya adalah menguji kode parser menggunakan sampel log mentah dengan berbagai format yang luas. Hal ini memungkinkan Anda menemukan log atau kasus ekstrem unik yang mungkin perlu ditangani oleh parser.
Menambahkan komentar deskriptif ke kode parser
Tambahkan komentar ke kode parser yang menjelaskan alasan pentingnya pernyataan, bukan fungsi pernyataan tersebut. Komentar ini 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}"
}
}
}
Menginisialisasi variabel perantara lebih awal
Sebelum mengekstrak nilai dari log mentah asli, inisialisasi variabel menengah 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 mendeteksi 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 menjadi
variabel perantara boolean, yang disebut _error_does_not_exist
. Ini tidak
memungkinkan Anda menggunakan variabel product
dalam pernyataan kondisional, 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 mengeksekusi 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 bersyarat untuk memeriksa apakah kolom ada. Selain itu, pernyataan
on_error
menangani error yang mungkin terjadi.
Mengonversi SHA-256 menjadi 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
Tidak jarang log masuk memiliki format log yang tidak terduga atau memiliki data yang diformat dengan buruk.
Anda dapat membuat 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
disetel 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
, berarti entri log yang masuk memiliki 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 format kolom sudah 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 diserap dengan format yang salah untuk jenis log yang ditentukan.
Gunakan filter drop
dengan variabel tag
sehingga kondisinya tercakup dalam tabel metrik penyerapan di BigQuery.
TAG_UNSUPPORTED
TAG_MALFORMED_ENCODING
TAG_MALFORMED_MESSAGE
TAG_NO_SECURITY_VALUE
Filter drop
menghentikan parser agar tidak memproses log mentah, menormalisasi kolom,
dan membuat data UDM. Log mentah asli masih diserap ke Chronicle
dan dapat ditelusuri menggunakan penelusuran log mentah di Chronicle.
Nilai yang diteruskan ke variabel tag
disimpan di kolom drop_reason_code
dalam tabel metrik Penyerapan. Anda dapat menjalankan kueri ad hoc terhadap tabel seperti 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 terkait validasi, misalnya kolom wajib diisi belum ditetapkan dalam data UDM. Error tersebut 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 data UDM yang dihasilkan tidak
menyertakan semua kolom UDM wajib seperti yang ditentukan oleh nilai yang ditetapkan ke metadata.event_type
. Berikut
adalah contoh tambahan yang dapat menyebabkan error ini:
- Jika
metadata.event_type
adalahUSER_LOGIN
dan kolom UDMtarget.user value
tidak ditetapkan. - Jika
metadata.event_type
adalahNETWORK_CONNECTION
dan kolom UDMtarget.hostname
tidak ditetapkan.
Untuk mengetahui informasi selengkapnya tentang kolom UDM metadata.event_type
dan kolom wajib, lihat panduan penggunaan UDM.
Salah satu opsi untuk memecahkan masalah jenis error ini adalah 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 diurai 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 melakukan inisialisasi variabel perantara dan menetapkan masing-masing variabel ke string statis.
- Kode di bagian Penetapan Kolom menetapkan nilai dalam variabel perantara ke kolom UDM.
Anda dapat meluaskan kode ini dengan menambahkan kolom UDM dan variabel perantara 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 nilainya ke variabel perantara.
Di bagian Ekstrak Tanggal, tambahkan kode yang mengekstrak stempel waktu peristiwa dari log mentah asli, mengubahnya, dan menetapkannya ke variabel perantara.
Bila perlu, ganti set nilai yang diinisialisasi di setiap variabel perantara 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
Ketika menggunakan fungsi Grok untuk mengekstrak nilai dari teks tidak terstruktur, Anda dapat menggunakan pernyataan ekspresi reguler dan pola Grok yang telah ditentukan. Pola grok membuat
kode lebih mudah dibaca. Jika ekspresi reguler tidak menyertakan karakter
singkat (seperti \w
, \s
), Anda dapat menyalin dan menempelkan pernyataan tersebut 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 dan ekspresi reguler Grok yang telah ditetapkan.
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 berperforma lebih baik. Misalnya, contoh berikut membutuhkan waktu kurang dari setengah langkah pemrosesan untuk mencocokkan. Untuk sumber log dengan volume yang berpotensi tinggi, ini adalah pertimbangan penting.
Memahami perbedaan antara ekspresi reguler RE2 dan PCRE
Parser Chronicle menggunakan RE2 sebagai mesin ekspresi reguler. Jika sudah terbiasa dengan sintaksis PCRE, Anda mungkin melihat perbedaannya. 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
Chronicle menyimpan data log mentah yang masuk dalam format yang dienkode JSON. Hal ini untuk
memastikan bahwa string karakter yang tampak seperti versi singkat 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 ini 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 nilai saja. Untuk mencocokkan garis miring terbalik di log mentah asli, gunakan empat garis miring terbalik dalam pernyataan ekstraksi.
Berikut ini 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, escape
karakter singkat ekspresi reguler dalam pernyataan ekstraksi.
Misalnya, ubah \s
menjadi \\s
.
Jangan ubah karakter khusus ekspresi reguler saat karakter khusus di-escape dua kali 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 dimodifikasi agar berfungsi di 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 dimodifikasi untuk kode parser | Deskripsi perubahan |
---|---|---|
\s |
\\s |
Karakter singkat harus di-escape. |
\. |
\\. |
Karakter yang sudah digunakan harus di-escape. |
\\" |
\\\" |
Karakter yang sudah digunakan harus di-escape. |
\] |
\\] |
Karakter yang sudah digunakan harus di-escape. |
\| |
\\| |
Karakter yang sudah digunakan harus di-escape. |
[^\\]+ |
[^\\\\]+ |
Karakter khusus dalam grup class karakter harus di-escape. |
\\\\ |
\\\\ |
Karakter khusus di luar kelompok 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 ini 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, 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 kolom ekspresi satu per satu.
Contoh berikut dimulai dengan menggunakan grup bernama (_catchall
) yang cocok dengan seluruh pesan. Kemudian, kode ini mem-build ekspresi secara bertahap dengan mencocokkan
bagian teks lainnya. Untuk setiap langkah, grup bernama _catchall
berisi lebih sedikit teks asli. Lanjutkan dan iterasi langkah demi langkah untuk mencocokkan pesan sampai Anda tidak lagi memerlukan grup bernama _catchall
.
Langkah | Ekspresi reguler dalam kode parser | Output grup tangkapan 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. |
Meloloskan karakter singkatan dalam ekspresi reguler
Jangan lupa 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 akan memiliki huruf
s
.
Ekspresi reguler standar | Output grup tangkapan bernama _firstWord |
---|---|
"^(?P<_firstWord>[^\s]+)\s.*$" |
"_firstWord": "Thi", |
Hal ini karena ekspresi reguler dalam kode parser memerlukan karakter escape
tambahan yang ditambahkan ke karakter pintasan. Pada contoh sebelumnya, \s
harus diubah menjadi \\s
.
Ekspresi reguler yang direvisi untuk kode parser | Output grup tangkapan bernama _firstWord |
---|---|
"^(?P<_firstWord>[^\\s]+)\\s.*$" |
"_firstWord": "This", |
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 tidak terstruktur dan ekspresi reguler standar yang ditulis untuk mengurai string. Terakhir, contoh ini menyertakan ekspresi reguler yang dimodifikasi yang berfungsi dalam kode parser.
Berikut ini adalah string teks asli.
User "BOB" logged on to workstation "DESKTOP-01".
Berikut ini 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\". |
Kelompokkan `_user` | 7-10 | BOB |
Grup 2. | 13-22 | logged on |
Kelompokkan `_device` | 40-50 | DESKTOP-01 |
Ini adalah ekspresi yang dimodifikasi. Ekspresi reguler RE2 standar dimodifikasi agar berfungsi dalam kode parser.
^.*?\\\"(?P<_user>[^\\\\]+)\\\"\\s(?:(logged\\son|logged\\soff))\\s.*?\\\"(?P<_device>[^\\\\]+)\\\"\\.$