Thursday

19-06-2025 Vol 19

How to Build Custom Filters with awk and sed Pipelines on Ubuntu 20.04

Cara Membuat Filter Kustom dengan Pipeline `awk` dan `sed` di Ubuntu 20.04

Dalam dunia administrasi sistem dan pengembangan perangkat lunak, kemampuan untuk memproses dan memanipulasi data teks secara efisien adalah keterampilan yang sangat berharga. Utilitas baris perintah seperti `awk` dan `sed` menawarkan kekuatan dan fleksibilitas yang luar biasa untuk tugas-tugas ini. Artikel ini akan memandu Anda melalui proses pembuatan filter kustom menggunakan pipeline `awk` dan `sed` di Ubuntu 20.04. Kami akan menjelajahi dasar-dasar, memberikan contoh praktis, dan membahas teknik tingkat lanjut untuk membantu Anda menguasai seni pemrosesan teks.

Daftar Isi

  1. Pendahuluan
    • Apa itu `awk` dan `sed`?
    • Mengapa Menggunakan `awk` dan `sed`?
    • Prasyarat
  2. Dasar-Dasar `awk`
    • Sintaks Dasar `awk`
    • Variabel dan Ekspresi `awk`
    • Pola dan Tindakan
    • Contoh Penggunaan Dasar `awk`
  3. Dasar-Dasar `sed`
    • Sintaks Dasar `sed`
    • Perintah Substitusi `sed`
    • Perintah Penghapusan `sed`
    • Contoh Penggunaan Dasar `sed`
  4. Membangun Pipeline dengan `awk` dan `sed`
    • Konsep Pipeline
    • Menggabungkan `awk` dan `sed`
    • Contoh Pipeline Sederhana
  5. Filter Kustom Tingkat Lanjut
    • Manipulasi String Tingkat Lanjut dengan `awk`
    • Ekspresi Reguler dalam `sed`
    • Menggunakan Variabel dan Fungsi dalam Pipeline
  6. Studi Kasus: Log Parsing dan Analisis
    • Ekstraksi Informasi dari Log
    • Memfilter Log Berdasarkan Kriteria
    • Agregasi dan Pelaporan Data Log
  7. Studi Kasus: Manipulasi Data CSV
    • Memproses File CSV dengan `awk`
    • Memformat Ulang Data CSV dengan `sed`
    • Menggabungkan dan Memfilter Data CSV
  8. Praktik Terbaik dan Tips
    • Kejelasan dan Keterbacaan
    • Penanganan Kesalahan
    • Efisiensi dan Kinerja
  9. Kesimpulan
    • Ringkasan Kekuatan `awk` dan `sed`
    • Langkah Selanjutnya dalam Pembelajaran Pemrosesan Teks

1. Pendahuluan

Apa itu `awk` dan `sed`?

`awk` dan `sed` adalah dua utilitas baris perintah yang sangat kuat yang digunakan untuk pemrosesan teks. `awk`, dinamai dari penciptanya Aho, Weinberger, dan Kernighan, adalah bahasa pemrograman yang berorientasi pada pemrosesan data berbasis pola. Ia sangat baik dalam memfilter, mentransformasi, dan menghasilkan laporan dari data terstruktur, terutama data yang disusun dalam kolom. `sed`, singkatan dari *stream editor*, adalah editor aliran non-interaktif yang memungkinkan Anda melakukan operasi substitusi, penghapusan, penyisipan, dan transformasi lainnya pada teks.

Mengapa Menggunakan `awk` dan `sed`?

Ada beberapa alasan mengapa `awk` dan `sed` merupakan alat yang sangat berharga:

  • Efisiensi: Utilitas ini dirancang untuk pemrosesan teks cepat dan efisien, bahkan pada file yang sangat besar.
  • Fleksibilitas: `awk` dan `sed` menawarkan berbagai opsi dan fitur untuk menangani berbagai tugas pemrosesan teks.
  • Otomatisasi: Anda dapat menggunakan `awk` dan `sed` dalam skrip shell untuk mengotomatiskan tugas pemrosesan teks.
  • Portabilitas: `awk` dan `sed` tersedia di hampir semua sistem operasi seperti Unix dan Linux, menjadikannya alat yang sangat portabel.
  • Kekuatan Pipeline: `awk` dan `sed` dapat digabungkan dalam pipeline untuk melakukan pemrosesan teks kompleks secara bertahap.

Prasyarat

Untuk mengikuti tutorial ini, Anda memerlukan:

  • Sistem Ubuntu 20.04 yang berfungsi.
  • Akses ke terminal baris perintah.
  • Pengetahuan dasar tentang perintah baris perintah Linux.

2. Dasar-Dasar `awk`

Sintaks Dasar `awk`

Sintaks dasar dari perintah `awk` adalah:

awk 'pattern { action }' filename

Di mana:

  • `pattern` adalah kondisi yang menentukan baris mana yang akan diproses.
  • `action` adalah kode yang akan dieksekusi untuk baris yang cocok dengan pola tersebut.
  • `filename` adalah nama file input. Jika tidak ada file yang ditentukan, `awk` membaca dari input standar.

Jika pola dihilangkan, tindakan akan diterapkan ke semua baris. Jika tindakan dihilangkan, `awk` akan mencetak setiap baris yang cocok dengan pola ke output standar.

Variabel dan Ekspresi `awk`

`awk` mendukung berbagai variabel bawaan dan ekspresi yang dapat Anda gunakan untuk memproses data teks. Beberapa variabel bawaan yang paling umum adalah:

  • `$0`: Seluruh baris input.
  • `$1`, `$2`, `$3`, …: Kolom-kolom (bidang-bidang) dalam baris input, dipisahkan oleh pemisah bidang (secara default, spasi putih).
  • `NF`: Jumlah bidang di baris saat ini.
  • `NR`: Nomor baris saat ini.
  • `FS`: Pemisah bidang input (secara default, spasi putih).
  • `RS`: Pemisah record input (secara default, baris baru).
  • `OFS`: Pemisah bidang output (secara default, spasi).
  • `ORS`: Pemisah record output (secara default, baris baru).

Anda juga dapat menggunakan ekspresi aritmatika, string, dan Boolean dalam `awk`. Misalnya:

  • `+`, `-`, `*`, `/`, `%`: Operator aritmatika.
  • `==`, `!=`, `>`, `<`, `>=`, `<=`: Operator perbandingan.
  • `&&`, `||`, `!`: Operator logika.
  • `~`, `!~`: Operator pencocokan ekspresi reguler.
  • `=`, `+=`, `-=`, `*=`, `/=`, `%=`: Operator penugasan.

Pola dan Tindakan

Pola dalam `awk` dapat berupa:

  • Ekspresi reguler: Mencocokkan baris yang mengandung string tertentu.
  • Ekspresi: Mengevaluasi benar atau salah.
  • Rentang: Menentukan rentang baris berdasarkan nomor baris atau pola.
  • `BEGIN` dan `END`: Pola khusus yang dijalankan sebelum dan sesudah pemrosesan file.

Tindakan dalam `awk` adalah blok kode yang dikelilingi oleh kurung kurawal `{}`. Tindakan dapat berisi:

  • Pernyataan cetak: `print` untuk mencetak data ke output standar.
  • Pernyataan penugasan: Menetapkan nilai ke variabel.
  • Pernyataan kondisional: `if` dan `else` untuk melakukan tindakan berdasarkan kondisi.
  • Loop: `for` dan `while` untuk melakukan tindakan berulang kali.
  • Fungsi: Memanggil fungsi bawaan atau fungsi yang ditentukan pengguna.

Contoh Penggunaan Dasar `awk`

Berikut adalah beberapa contoh penggunaan dasar `awk`:

  1. Mencetak semua baris dari sebuah file:
    awk '{ print }' myfile.txt
  2. Mencetak hanya baris yang mengandung kata “error”:
    awk '/error/ { print }' myfile.txt
  3. Mencetak kolom pertama dari setiap baris:
    awk '{ print $1 }' myfile.txt
  4. Mencetak kolom pertama dan ketiga dari setiap baris, dipisahkan oleh koma:
    awk '{ print $1 "," $3 }' myfile.txt
  5. Mencetak nomor baris dan baris itu sendiri untuk setiap baris:
    awk '{ print NR, $0 }' myfile.txt
  6. Menghitung jumlah baris dalam sebuah file:
    awk 'END { print NR }' myfile.txt

3. Dasar-Dasar `sed`

Sintaks Dasar `sed`

Sintaks dasar dari perintah `sed` adalah:

sed 'command' filename

Di mana:

  • `command` adalah perintah `sed` yang akan dieksekusi.
  • `filename` adalah nama file input. Jika tidak ada file yang ditentukan, `sed` membaca dari input standar.

`sed` memproses setiap baris dari file input satu per satu, menerapkan perintah yang ditentukan ke setiap baris, dan mencetak hasilnya ke output standar. Secara default, `sed` tidak mengubah file input. Untuk mengubah file input secara langsung, Anda dapat menggunakan opsi `-i`.

Perintah Substitusi `sed`

Perintah substitusi `sed` adalah salah satu perintah yang paling umum digunakan. Sintaksnya adalah:

sed 's/pattern/replacement/flags' filename

Di mana:

  • `s` menunjukkan perintah substitusi.
  • `pattern` adalah ekspresi reguler yang akan dicari.
  • `replacement` adalah string yang akan menggantikan pola yang cocok.
  • `flags` adalah opsi tambahan yang memodifikasi perilaku perintah substitusi. Beberapa flag yang umum adalah:
    • `g`: Mengganti semua kemunculan pola dalam baris.
    • `i`: Pencocokan tanpa memperhatikan huruf besar/kecil.
    • `n`: Mengganti kemunculan pola ke-n.
    • `p`: Mencetak baris yang dimodifikasi.

Perintah Penghapusan `sed`

Perintah penghapusan `sed` menghapus baris yang cocok dengan pola tertentu. Sintaksnya adalah:

sed '/pattern/d' filename

Di mana:

  • `d` menunjukkan perintah penghapusan.
  • `pattern` adalah ekspresi reguler yang akan dicari. Baris yang cocok dengan pola ini akan dihapus.

Contoh Penggunaan Dasar `sed`

Berikut adalah beberapa contoh penggunaan dasar `sed`:

  1. Mengganti kemunculan pertama kata “old” dengan “new” dalam setiap baris:
    sed 's/old/new/' myfile.txt
  2. Mengganti semua kemunculan kata “old” dengan “new” dalam setiap baris:
    sed 's/old/new/g' myfile.txt
  3. Menghapus semua baris yang mengandung kata “error”:
    sed '/error/d' myfile.txt
  4. Menghapus baris pertama dari sebuah file:
    sed '1d' myfile.txt
  5. Menghapus baris terakhir dari sebuah file:
    sed '$d' myfile.txt
  6. Menghapus semua baris kosong dari sebuah file:
    sed '/^$/d' myfile.txt

4. Membangun Pipeline dengan `awk` dan `sed`

Konsep Pipeline

Pipeline adalah serangkaian perintah yang dihubungkan oleh operator pipa (`|`). Output dari perintah pertama menjadi input untuk perintah kedua, dan seterusnya. Ini memungkinkan Anda untuk melakukan pemrosesan teks kompleks secara bertahap, dengan setiap perintah dalam pipeline melakukan tugas tertentu.

Menggabungkan `awk` dan `sed`

`awk` dan `sed` seringkali dapat digabungkan dalam pipeline untuk memanfaatkan kekuatan masing-masing. Misalnya, Anda dapat menggunakan `awk` untuk memfilter dan memformat data, dan kemudian menggunakan `sed` untuk melakukan substitusi atau penghapusan lebih lanjut.

Contoh Pipeline Sederhana

Berikut adalah beberapa contoh pipeline sederhana yang menggabungkan `awk` dan `sed`:

  1. Mencetak kolom pertama dan ketiga dari setiap baris yang mengandung kata “error”, dan kemudian mengganti semua spasi dengan garis bawah:
    awk '/error/ { print $1, $3 }' myfile.txt | sed 's/ /_/g'
  2. Menghapus semua baris yang mengandung kata “debug” dan kemudian mengganti semua kemunculan “INFO” dengan “Information”:
    sed '/debug/d' myfile.txt | sed 's/INFO/Information/g'
  3. Mengekstrak alamat IP dari file log dan kemudian menghitung jumlah kemunculan setiap alamat IP:
    awk '{ print $1 }' access.log | sort | uniq -c

5. Filter Kustom Tingkat Lanjut

Manipulasi String Tingkat Lanjut dengan `awk`

`awk` menyediakan berbagai fungsi string bawaan yang memungkinkan Anda melakukan manipulasi string tingkat lanjut. Beberapa fungsi yang paling berguna adalah:

  • `length(string)`: Mengembalikan panjang string.
  • `substr(string, start, length)`: Mengembalikan substring dari string, dimulai dari posisi `start` dengan panjang `length`.
  • `index(string, substring)`: Mengembalikan posisi kemunculan pertama `substring` dalam `string`.
  • `split(string, array, separator)`: Membagi `string` menjadi array berdasarkan `separator`.
  • `gsub(regexp, replacement, string)`: Mengganti semua kemunculan ekspresi reguler `regexp` dengan `replacement` dalam `string`.
  • `tolower(string)`: Mengonversi `string` menjadi huruf kecil.
  • `toupper(string)`: Mengonversi `string` menjadi huruf besar.

Contoh:

  1. Mencetak panjang setiap baris:
    awk '{ print length($0) }' myfile.txt
  2. Mencetak 10 karakter pertama dari setiap baris:
    awk '{ print substr($0, 1, 10) }' myfile.txt
  3. Mencari posisi kata “error” dalam setiap baris:
    awk '{ print index($0, "error") }' myfile.txt
  4. Membagi setiap baris menjadi array berdasarkan koma dan mencetak elemen kedua:
    awk '{ split($0, a, ","); print a[2] }' myfile.csv
  5. Mengganti semua spasi dengan garis bawah dalam setiap baris:
    awk '{ gsub(/ /, "_", $0); print $0 }' myfile.txt
  6. Mengonversi semua baris menjadi huruf kecil:
    awk '{ print tolower($0) }' myfile.txt

Ekspresi Reguler dalam `sed`

`sed` sangat bergantung pada ekspresi reguler untuk mencocokkan pola dalam teks. Ekspresi reguler adalah pola yang digunakan untuk mencocokkan string teks. `sed` menggunakan Basic Regular Expressions (BRE) secara default, tetapi Anda dapat menggunakan Extended Regular Expressions (ERE) dengan opsi `-E`.

Beberapa karakter meta yang umum digunakan dalam ekspresi reguler adalah:

  • `.`: Mencocokkan karakter apa pun kecuali baris baru.
  • `*`: Mencocokkan nol atau lebih kemunculan karakter sebelumnya.
  • `+`: Mencocokkan satu atau lebih kemunculan karakter sebelumnya (ERE).
  • `?`: Mencocokkan nol atau satu kemunculan karakter sebelumnya (ERE).
  • `[]`: Mencocokkan salah satu karakter dalam kurung siku.
  • `[^]`: Mencocokkan karakter apa pun kecuali karakter dalam kurung siku.
  • `^`: Mencocokkan awal baris.
  • `$`: Mencocokkan akhir baris.
  • `\`: Menghilangkan arti khusus dari karakter meta.
  • `\(` dan `\)`: Mengelompokkan bagian dari ekspresi reguler dan menyimpan kecocokan untuk digunakan kembali (disebut backreference).
  • `\1`, `\2`, …: Mereferensikan kembali kecocokan yang disimpan oleh kurung.

Contoh:

  1. Mengganti semua angka dengan “X”:
    sed 's/[0-9]/X/g' myfile.txt
  2. Menghapus semua karakter non-alfanumerik:
    sed 's/[^a-zA-Z0-9]//g' myfile.txt
  3. Menukar kata pertama dan terakhir dalam setiap baris (membutuhkan ERE dengan `-E`):
    sed -E 's/^(\S+)\s+(.*)\s+(\S+)$/\3 \2 \1/' myfile.txt
  4. Menghapus semua baris yang dimulai dengan spasi:
    sed '/^ /d' myfile.txt

Menggunakan Variabel dan Fungsi dalam Pipeline

Anda dapat menggunakan variabel dan fungsi dalam pipeline untuk membuat filter yang lebih kompleks dan dinamis. Misalnya, Anda dapat menggunakan variabel untuk menyimpan nilai yang akan digunakan dalam beberapa perintah, atau Anda dapat menggunakan fungsi untuk melakukan pemrosesan yang kompleks.

Contoh:

  1. Menetapkan nilai ke variabel dan menggunakan variabel tersebut dalam perintah `awk`:
    my_variable="error"; awk -v var="$my_variable" '$0 ~ var { print }' myfile.txt
  2. Menggunakan fungsi `awk` untuk memvalidasi alamat IP:
    awk '{ if (match($1, /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)) print $1 " is a valid IP address"; else print $1 " is not a valid IP address" }' myfile.txt

6. Studi Kasus: Log Parsing dan Analisis

Ekstraksi Informasi dari Log

Salah satu kasus penggunaan yang paling umum untuk `awk` dan `sed` adalah memparsing dan menganalisis file log. File log seringkali mengandung sejumlah besar data, dan `awk` dan `sed` dapat digunakan untuk mengekstrak informasi tertentu dari log ini.

Misalkan Anda memiliki file log bernama `access.log` yang berisi baris-baris berikut:

  
  192.168.1.1 - - [01/Jan/2023:00:00:00 +0000] "GET /index.html HTTP/1.1" 200 1000
  192.168.1.2 - - [01/Jan/2023:00:00:05 +0000] "POST /login HTTP/1.1" 302 500
  192.168.1.1 - - [01/Jan/2023:00:00:10 +0000] "GET /about.html HTTP/1.1" 200 1200
  192.168.1.3 - - [01/Jan/2023:00:00:15 +0000] "GET /contact.html HTTP/1.1" 404 800
  
  

Anda dapat menggunakan `awk` untuk mengekstrak alamat IP, waktu, dan URL dari file log ini:

awk '{ print $1, $4, $7 }' access.log

Output:

  
  192.168.1.1 [01/Jan/2023:00:00:00 /index.html
  192.168.1.2 [01/Jan/2023:00:00:05 /login
  192.168.1.1 [01/Jan/2023:00:00:10 /about.html
  192.168.1.3 [01/Jan/2023:00:00:15 /contact.html
  
  

Memfilter Log Berdasarkan Kriteria

Anda juga dapat menggunakan `awk` dan `sed` untuk memfilter log berdasarkan kriteria tertentu. Misalnya, Anda dapat memfilter log untuk hanya menampilkan baris yang mengandung kode status 404:

awk '$9 == 404 { print }' access.log

Output:

192.168.1.3 - - [01/Jan/2023:00:00:15 +0000] "GET /contact.html HTTP/1.1" 404 800

Atau, Anda dapat memfilter log untuk hanya menampilkan baris yang berasal dari alamat IP tertentu:

awk '$1 == "192.168.1.1" { print }' access.log

Output:

  
  192.168.1.1 - - [01/Jan/2023:00:00:00 +0000] "GET /index.html HTTP/1.1" 200 1000
  192.168.1.1 - - [01/Jan/2023:00:00:10 +0000] "GET /about.html HTTP/1.1" 200 1200
  
  

Agregasi dan Pelaporan Data Log

`awk` juga dapat digunakan untuk melakukan agregasi dan pelaporan data log. Misalnya, Anda dapat menggunakan `awk` untuk menghitung jumlah permintaan untuk setiap URL:

awk '{ count[$7]++ } END { for (url in count) print url, count[url] }' access.log

Output:

  
  /index.html 1
  /login 1
  /about.html 1
  /contact.html 1
  
  

Atau, Anda dapat menggunakan `awk` untuk menghitung jumlah permintaan dari setiap alamat IP:

awk '{ count[$1]++ } END { for (ip in count) print ip, count[ip] }' access.log

Output:

  
  192.168.1.1 2
  192.168.1.2 1
  192.168.1.3 1
  
  

7. Studi Kasus: Manipulasi Data CSV

Memproses File CSV dengan `awk`

File CSV (Comma Separated Values) adalah format file yang umum digunakan untuk menyimpan data tabular. `awk` sangat baik dalam memproses file CSV karena dirancang untuk memproses data yang disusun dalam kolom.

Misalkan Anda memiliki file CSV bernama `data.csv` yang berisi data berikut:

  
  Name,Age,City
  John,30,New York
  Jane,25,London
  Peter,40,Paris
  
  

Anda dapat menggunakan `awk` untuk mencetak nama dan usia dari setiap baris:

awk -F"," 'NR > 1 { print $1, $2 }' data.csv

Output:

  
  John 30
  Jane 25
  Peter 40
  
  

Perhatikan opsi `-F”,”` yang menentukan bahwa pemisah bidang adalah koma. `NR > 1` memastikan bahwa baris header tidak diproses.

Memformat Ulang Data CSV dengan `sed`

Anda dapat menggunakan `sed` untuk memformat ulang data CSV. Misalnya, Anda dapat mengganti koma dengan tab:

sed 's/,/\t/g' data.csv

Output:

  
  Name    Age     City
  John    30      New York
  Jane    25      London
  Peter   40      Paris
  
  

Menggabungkan dan Memfilter Data CSV

Anda dapat menggabungkan `awk` dan `sed` untuk menggabungkan dan memfilter data CSV. Misalnya, Anda dapat memfilter data untuk hanya menampilkan baris yang usianya lebih dari 30 tahun dan kemudian mengganti koma dengan titik koma:

awk -F"," 'NR > 1 && $2 > 30 { print }' data.csv | sed 's/,/;/g'

Output:

Peter;40;Paris

8. Praktik Terbaik dan Tips

Kejelasan dan Keterbacaan

  • Berikan Komentar: Tambahkan komentar ke skrip `awk` dan `sed` Anda untuk menjelaskan apa yang dilakukan setiap bagian kode.
  • Format Kode: Gunakan indentasi dan spasi yang konsisten untuk membuat kode Anda lebih mudah dibaca.
  • Nama Variabel yang Bermakna: Gunakan nama variabel yang deskriptif untuk memudahkan pemahaman kode Anda.

Penanganan Kesalahan

  • Periksa Kode Status: Periksa kode status dari perintah `awk` dan `sed` untuk memastikan bahwa mereka berhasil dieksekusi.
  • Tangani Kesalahan: Tangani kesalahan dengan tepat, misalnya dengan mencetak pesan kesalahan ke output standar kesalahan.
  • Validasi Input: Validasi input untuk memastikan bahwa itu dalam format yang diharapkan.

Efisiensi dan Kinerja

  • Gunakan Ekspresi Reguler yang Efisien: Gunakan ekspresi reguler yang efisien untuk meminimalkan waktu pemrosesan.
  • Hindari Pemrosesan yang Tidak Perlu: Hindari melakukan pemrosesan yang tidak perlu. Misalnya, jika Anda hanya membutuhkan kolom tertentu, jangan memproses seluruh baris.
  • Pertimbangkan Penggunaan `gawk`: Jika Anda memerlukan kinerja yang lebih baik, pertimbangkan untuk menggunakan `gawk`, implementasi GNU dari `awk`, yang seringkali lebih cepat daripada implementasi lainnya.

9. Kesimpulan

Ringkasan Kekuatan `awk` dan `sed`

`awk` dan `sed` adalah utilitas baris perintah yang sangat kuat yang memungkinkan Anda melakukan berbagai tugas pemrosesan teks. `awk` sangat baik dalam memfilter, mentransformasi, dan menghasilkan laporan dari data terstruktur. `sed` sangat baik dalam melakukan substitusi, penghapusan, dan transformasi lainnya pada teks. Dengan menggabungkan `awk` dan `sed` dalam pipeline, Anda dapat melakukan pemrosesan teks yang kompleks secara efisien.

Langkah Selanjutnya dalam Pembelajaran Pemrosesan Teks

Artikel ini hanya memperkenalkan dasar-dasar `awk` dan `sed`. Untuk mempelajari lebih lanjut, Anda dapat menjelajahi:

  • Dokumentasi Resmi: Dokumentasi resmi `awk` dan `sed` memberikan informasi yang komprehensif tentang fitur dan opsi yang tersedia.
  • Tutorial Online: Ada banyak tutorial online yang mencakup berbagai aspek `awk` dan `sed`.
  • Buku: Ada beberapa buku yang membahas `awk` dan `sed` secara mendalam.
  • Latihan Praktis: Cara terbaik untuk mempelajari `awk` dan `sed` adalah dengan berlatih. Cobalah untuk menerapkan `awk` dan `sed` ke berbagai tugas pemrosesan teks yang berbeda.

Dengan dedikasi dan latihan, Anda dapat menguasai seni pemrosesan teks dengan `awk` dan `sed` dan meningkatkan produktivitas Anda secara signifikan.

“`

omcoding

Leave a Reply

Your email address will not be published. Required fields are marked *