Regular Expressions (RegEx) in Python

fungsi-fungsi Python RegEx secara rinci, termasuk metacharacters dan special sequences, serta memberikan contoh implementasi dalam industri.

  1. Metacharacters dalam RegEx:
  • . (titik): Mencocokkan karakter apapun kecuali newline.
  • ^ (caret): Mencocokkan awal string.
  • $ (dollar): Mencocokkan akhir string.
    • * (asterisk): Mencocokkan 0 atau lebih kemunculan karakter sebelumnya.
    • + (plus): Mencocokkan 1 atau lebih kemunculan karakter sebelumnya.
  • ? (question mark): Mencocokkan 0 atau 1 kemunculan karakter sebelumnya.
  • {} (curly braces): Menentukan jumlah kemunculan karakter sebelumnya.
  • [] (square brackets): Mencocokkan satu karakter dari set karakter.
  • | (pipe): Mencocokkan salah satu dari beberapa alternatif.
  • () (parentheses): Mengelompokkan pola dan membuat grup.
  • \ (backslash): Menghilangkan arti khusus dari karakter metacharacter.
  1. Special Sequences dalam RegEx:

  • \d: Mencocokkan digit (0-9).
  • \D: Mencocokkan karakter non-digit [^0-9]..
  • \w: Mencocokkan karakter word (a-z, A-Z, 0-9, _).[a-zA-Z0-9]
  • \W: Mencocokkan karakter non-word. [a-zA-Z0-9]
  • \s: Mencocokkan whitespace (spasi, tab, newline)  [\t\n\r\f\v]
  • \S: Mencocokkan karakter non-whitespace. [^\t\n\r\f\v]
  • \b: Mencocokkan batas kata.
  • \B: Mencocokkan posisi yang bukan batas kata.

    3. RegEx Functions in Python

  • re.match(): Periksa untuk pertandingan hanya di awal string.
  • re.search(): Pencarian untuk munculnya pola pertama dalam string.
  • re.findall(): Mengembalikan daftar yang berisi semua pertandingan.
  • re.finditer(): Mengembalikan iterator yang menghasilkan objek yang cocok.
  • re.split(): Membagi string dengan kejadian pola.
  • re.sub(): Mengganti satu atau lebih pertandingan dengan string.

Contoh implementasi RegEx dalam industri:

  1. Validasi format data input:

a. Validasi nomor telepon Indonesia:

python
import re def validate_phone_number(phone): pattern = r'^(\+62|62|0)8[1-9][0-9]{7,10}$' return bool(re.match(pattern, phone)) # Contoh penggunaan print(validate_phone_number('+6281234567890')) # True print(validate_phone_number('081234567890')) # True print(validate_phone_number('8123456789')) # False

Penjelasan:

  • ^ dan $ memastikan pola cocok dari awal hingga akhir string.
  • (\+62|62|0) mencocokkan kode negara atau awalan '0'.
  • 8 mencocokkan digit pertama nomor seluler Indonesia.
  • [1-9] mencocokkan digit kedua (1-9).
  • [0-9]{7,10} mencocokkan 7 hingga 10 digit terakhir.

Extracting Phone Numbers

python

import re

def extract_phone_numbers(text):
    pattern = r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b'
    return re.findall(pattern, text)

text = "Contact us at 123-456-7890 or 987.654.3210"
phone_numbers = extract_phone_numbers(text)
print(phone_numbers)  # Output: ['123-456-7890', '987.654.3210']

b. Validasi alamat email:

python
import re def validate_email(email): pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' return bool(re.match(pattern, email)) # Contoh penggunaan print(validate_email('user@example.com')) # True print(validate_email('invalid.email@')) # False

Penjelasan:

  • [a-zA-Z0-9._%+-]+ mencocokkan username email.
  • @ mencocokkan karakter '@'.
  • [a-zA-Z0-9.-]+ mencocokkan domain name.
  • \.[a-zA-Z]{2,} mencocokkan top-level domain (minimal 2 karakter).

Validating Email Addresses

python

import re

def validate_email(email):
    pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
    if re.match(pattern, email):
        return True
    return False

emails = ['test@example.com', 'invalid-email', 'user@domain.co']

valid_emails = [email for email in emails if validate_email(email)]
print(valid_emails)  # Output: ['test@example.com', 'user@domain.co']

  1. Ekstraksi informasi dari teks tidak terstruktur:
python
import re def extract_dates(text): pattern = r'\b(\d{1,2}/\d{1,2}/\d{4}|\d{1,2}-\d{1,2}-\d{4})\b' return re.findall(pattern, text) # Contoh penggunaan report = """ Laporan Keuangan Triwulan I 2024 Tanggal: 15/04/2024 Periode: 01-01-2024 sampai 31-03-2024 """ dates = extract_dates(report) print(dates) # ['15/04/2024', '01-01-2024', '31-03-2024']

Penjelasan:

  • Pattern mencocokkan format tanggal DD/MM/YYYY atau DD-MM-YYYY.
  • \b memastikan tanggal adalah kata terpisah.
  • \d{1,2} mencocokkan 1 atau 2 digit untuk hari dan bulan.
  • \d{4} mencocokkan 4 digit untuk tahun.
  1. Pencocokan dan penggantian pola teks:
python
import re def anonymize_data(text): # Anonymize email addresses text = re.sub(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', '[EMAIL]', text) # Anonymize phone numbers text = re.sub(r'\b(\+62|62|0)8[1-9][0-9]{7,10}\b', '[PHONE]', text) return text # Contoh penggunaan original_text = """ Nama: John Doe Email: john.doe@example.com Telepon: +6281234567890 """ anonymized_text = anonymize_data(original_text) print(anonymized_text)

Output:

Nama: John Doe Email: [EMAIL] Telepon: [PHONE]

Penjelasan:

  • re.sub() digunakan untuk mengganti pola yang cocok dengan teks pengganti.
  • Pattern email dan nomor telepon sama seperti contoh sebelumnya.

4. Cleaning Up Text Data

python

import re

def clean_text(text):
    # Remove HTML tags
    text = re.sub(r'<.*?>', '', text)
    # Remove non-alphanumeric characters
    text = re.sub(r'[^a-zA-Z0-9\s]', '', text)
    # Remove extra whitespace
    text = re.sub(r'\s+', ' ', text).strip()
    return text

html_text = "<p>This is a <b>bold</b> move.</p>"
cleaned_text = clean_text(html_text)
print(cleaned_text)  # Output: "This is a bold move"


5. Parsing Logs

python

import re

def parse_logs(log):
    pattern = r'(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) (\w+) (.*)'
    match = re.search(pattern, log)
    if match:
        return {
            'date': match.group(1),
            'time': match.group(2),
            'level': match.group(3),
            'message': match.group(4)
        }
    return None

log_entry = "2023-07-03 14:23:07 ERROR Something went wrong."
parsed_log = parse_logs(log_entry)
print(parsed_log)
# Output: {'date': '2023-07-03', 'time': '14:23:07', 'level': 'ERROR', 'message': 'Something went wrong.'}

Implementasi ini dapat digunakan dalam industri untuk:

  1. Meningkatkan keamanan data dengan mengaburkan informasi sensitif sebelum menyimpan atau mentransmisikan data.
  2. Memastikan konsistensi format data input, mengurangi kesalahan dan meningkatkan kualitas data.
  3. Mengotomatisasi ekstraksi informasi penting dari dokumen tidak terstruktur, menghemat waktu dan mengurangi kesalahan manual.
  4. Memudahkan analisis data dengan mengekstrak dan menstandarisasi format informasi tertentu dari berbagai sumber.

Dengan menggunakan RegEx, perusahaan dapat meningkatkan efisiensi operasional, mengurangi risiko kesalahan manusia, dan memproses data dengan lebih cepat dan akurat.

Tambahan :

  1. Ekstraksi informasi dari log server:

Misalkan kita memiliki log server dengan format sebagai berikut:


[2024-03-15 08:45:32] INFO: User 'johndoe' logged in from IP 192.168.1.100 [2024-03-15 09:12:45] ERROR: Database connection failed [2024-03-15 10:30:18] WARNING: High CPU usage detected (85%)

Kita dapat menggunakan RegEx untuk mengekstrak informasi penting dari log ini:

python

import re def parse_log(log_text): pattern = r'\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (\w+): (.+)' entries = [] for line in log_text.split('\n'): match = re.match(pattern, line) if match: timestamp, level, message = match.groups() entries.append({ 'timestamp': timestamp, 'level': level, 'message': message }) return entries # Contoh penggunaan log_text = """ [2024-03-15 08:45:32] INFO: User 'johndoe' logged in from IP 192.168.1.100 [2024-03-15 09:12:45] ERROR: Database connection failed [2024-03-15 10:30:18] WARNING: High CPU usage detected (85%) """ parsed_logs = parse_log(log_text) for entry in parsed_logs: print(f"Time: {entry['timestamp']}, Level: {entry['level']}, Message: {entry['message']}")

Penjelasan:

  • Pattern \[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] mencocokkan timestamp dalam kurung siku.
  • (\w+): mencocokkan level log (INFO, ERROR, WARNING).
  • (.+) mencocokkan sisa pesan log.
  • re.match() digunakan untuk mencocokkan pola dari awal string.
  • match.groups() mengembalikan tuple dari grup yang cocok.
  1. Validasi dan ekstraksi URL:
python

import re def extract_urls(text): pattern = r'https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)' return re.findall(pattern, text) def validate_url(url): pattern = r'^https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)$' return bool(re.match(pattern, url)) # Contoh penggunaan text = "Kunjungi website kami di https://www.example.com atau http://example.org untuk informasi lebih lanjut." urls = extract_urls(text) print("URLs ditemukan:", urls) for url in urls: print(f"URL '{url}' valid: {validate_url(url)}")

Penjelasan pattern URL:

  • https?:// mencocokkan "http://" atau "https://".
  • (?:www\.)? mencocokkan "www." opsional.
  • [-a-zA-Z0-9@:%._\+~#=]{1,256} mencocokkan nama domain.
  • \.[a-zA-Z0-9()]{1,6} mencocokkan top-level domain.
  • \b memastikan batas kata.
  • (?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*) mencocokkan path dan query string opsional.
  1. Pemrosesan dan normalisasi teks:
python

import re def normalize_text(text): # Menghapus karakter non-alfanumerik kecuali spasi text = re.sub(r'[^a-zA-Z0-9\s]', '', text) # Mengganti beberapa spasi berturut-turut dengan satu spasi text = re.sub(r'\s+', ' ', text) # Mengubah teks menjadi lowercase text = text.lower() return text.strip() # Contoh penggunaan original_text = " Ini adalah CONTOH teks yang akan di-normalize!!! " normalized_text = normalize_text(original_text) print(f"Original: '{original_text}'") print(f"Normalized: '{normalized_text}'")

Penjelasan:

  • [^a-zA-Z0-9\s] mencocokkan karakter yang bukan alfanumerik atau spasi.
  • \s+ mencocokkan satu atau lebih karakter whitespace.
  • strip() menghapus whitespace di awal dan akhir string.
  1. Ekstraksi informasi dari HTML:
python

import re def extract_links(html): pattern = r'<a\s+(?:[^>]*?\s+)?href="([^"]*)"' return re.findall(pattern, html) def extract_image_sources(html): pattern = r'<img\s+(?:[^>]*?\s+)?src="([^"]*)"' return re.findall(pattern, html) # Contoh penggunaan html_content = """ <html> <body> <a href="https://www.example.com">Link 1</a> <img src="image1.jpg" alt="Image 1"> <a href="/page2.html">Link 2</a> <img src="https://example.com/image2.png" alt="Image 2"> </body> </html> """ links = extract_links(html_content) images = extract_image_sources(html_content) print("Links:", links) print("Image sources:", images)

Penjelasan:

  • Pattern untuk link: <a\s+(?:[^>]*?\s+)?href="([^"]*)"
    • <a mencocokkan tag pembuka anchor.
    • \s+ mencocokkan satu atau lebih whitespace.
    • (?:[^>]*?\s+)? mencocokkan atribut opsional sebelum href.
    • href="([^"]*)" mencocokkan atribut href dan mengambil nilainya.
  • Pattern untuk gambar: <img\s+(?:[^>]*?\s+)?src="([^"]*)"
    • Mirip dengan pattern link, tetapi untuk tag <img> dan atribut src.

Implementasi-implementasi ini dapat digunakan dalam berbagai industri untuk:

  1. Analisis log: Memudahkan pemantauan sistem dan troubleshooting dengan cepat mengekstrak informasi penting dari log server.
  2. Keamanan web: Validasi URL dapat membantu mencegah serangan phishing dan memastikan integritas tautan.
  3. Pemrosesan bahasa alami: Normalisasi teks membantu dalam analisis sentimen, klasifikasi teks, dan tugas NLP lainnya.
  4. Web scraping: Ekstraksi informasi dari HTML memungkinkan pengumpulan data otomatis dari situs web.

RegEx sangat kuat dan fleksibel, tetapi juga dapat menjadi kompleks. Penting untuk memahami trade-off antara kompleksitas pattern dan kinerja, terutama ketika bekerja dengan dataset besar. Dalam beberapa kasus, parser HTML atau XML khusus mungkin lebih sesuai daripada RegEx untuk memproses markup yang kompleks.

Tambahan Example :

  1. Parsing CSV dengan RegEx:

Meskipun Python memiliki modul csv bawaan, RegEx dapat berguna untuk parsing CSV yang memiliki format tidak standar atau kompleks.

python

import re def parse_csv(csv_string): pattern = r''' (?:^|,) # Awal baris atau koma (?=[^"]|"(?:[^"]|"")*")? # Look-ahead untuk menentukan apakah field dikutip atau tidak ([^,]+) # Capture grup untuk field tanpa kutip |"([^"]*(?:""[^"]*)*)" # Capture grup untuk field dengan kutip ''' rows = [] for line in csv_string.strip().split('\n'): row = [] for match in re.finditer(pattern, line, re.VERBOSE): field = match.group(1) or match.group(2).replace('""', '"') row.append(field.strip()) rows.append(row) return rows # Contoh penggunaan csv_data = ''' Name,Age,City "Doe, John",30,"New York, NY" "Smith, Jane",25,London ''' parsed_data = parse_csv(csv_data) for row in parsed_data: print(row)

Penjelasan:

  • Pola RegEx ini menangani field dengan dan tanpa tanda kutip.
  • re.VERBOSE memungkinkan kita menulis pola RegEx yang lebih mudah dibaca dengan komentar.
  • (?:^|,) adalah non-capturing group yang mencocokkan awal baris atau koma.
  • (?=[^"]|"(?:[^"]|"")*")? adalah positive lookahead yang menentukan apakah field dikutip atau tidak.
  • ([^,]+) menangkap field tanpa tanda kutip.
  • "([^"]*(?:""[^"]*)*)" menangkap field dengan tanda kutip, termasuk tanda kutip ganda di dalamnya.
  1. Validasi password yang kompleks:
python

import re def validate_password(password): pattern = r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$' return bool(re.match(pattern, password)) # Contoh penggunaan passwords = [ "Weak123", "StrongPass1!", "NoUpperCase1!", "NoLowerCase1!", "NoNumber!", "NoSpecial1", "Short1!", ] for password in passwords: print(f"'{password}' is valid: {validate_password(password)}")

Penjelasan pattern:

  • ^ dan $ memastikan pola cocok dari awal hingga akhir string.
  • (?=.*[a-z]) positive lookahead untuk memastikan setidaknya satu huruf kecil.
  • (?=.*[A-Z]) positive lookahead untuk memastikan setidaknya satu huruf besar.
  • (?=.*\d) positive lookahead untuk memastikan setidaknya satu angka.
  • (?=.*[@$!%*?&]) positive lookahead untuk memastikan setidaknya satu karakter khusus.
  • [A-Za-z\d@$!%*?&]{8,} memastikan password terdiri dari karakter yang diizinkan dan minimal 8 karakter.
  1. Ekstraksi dan validasi ISBN:
python

import re def extract_and_validate_isbn(text): isbn_pattern = r'(?:ISBN(?:-1[03])?:?\s*)?(?=[0-9X]{10}$|(?=(?:[0-9]+[-\s]){3})[-\s0-9X]{13}$|97[89][0-9]{10}$|(?=(?:[0-9]+[-\s]){4})[-\s0-9]{17}$)(?:97[89][-\s]?)?[0-9]{1,5}[-\s]?[0-9]+[-\s]?[0-9]+[-\s]?[0-9X]' isbns = re.findall(isbn_pattern, text) valid_isbns = [] for isbn in isbns: # Menghapus karakter non-digit dan 'X' clean_isbn = re.sub(r'[^0-9X]', '', isbn) if len(clean_isbn) == 10: valid_isbns.append(validate_isbn10(clean_isbn)) elif len(clean_isbn) == 13: valid_isbns.append(validate_isbn13(clean_isbn)) return valid_isbns def validate_isbn10(isbn): if len(isbn) != 10: return False total = sum((10 - i) * (9 if x == 'X' else int(x)) for i, x in enumerate(isbn)) return total % 11 == 0 def validate_isbn13(isbn): if len(isbn) != 13: return False total = sum((3 if i % 2 else 1) * int(x) for i, x in enumerate(isbn)) return total % 10 == 0 # Contoh penggunaan text = """ Beberapa contoh ISBN: ISBN-10: 0-306-40615-2 ISBN-13: 978-0-306-40615-7 Invalid: 1234567890 """ valid_isbns = extract_and_validate_isbn(text) print("Valid ISBNs:", valid_isbns)

Penjelasan:

  • Pattern ISBN mencocokkan berbagai format ISBN-10 dan ISBN-13, termasuk dengan atau tanpa tanda hubung dan spasi.
  • validate_isbn10 dan validate_isbn13 mengimplementasikan algoritma pengecekan digit untuk masing-masing format ISBN.
  1. Named Groups dan Backreferences:
python

import re def parse_html_tag(html): pattern = r'<(?P<tag>[a-zA-Z0-9]+)(?P<attrs>\s+[^>]*)?>(?P<content>.*?)</(?P=tag)>' match = re.search(pattern, html, re.DOTALL) if match: return { 'tag': match.group('tag'), 'attributes': match.group('attrs').strip(), 'content': match.group('content') } return None # Contoh penggunaan html_snippet = '<div class="container">This is some content</div>' result = parse_html_tag(html_snippet) print(result)

Penjelasan:

  • (?P<name>...) digunakan untuk membuat named capture groups.
  • (?P=tag) adalah backreference ke named group 'tag', memastikan tag penutup cocok dengan tag pembuka.
  • re.DOTALL memungkinkan . untuk mencocokkan newline.

Teknik-teknik lanjutan ini mendemonstrasikan kekuatan dan fleksibilitas RegEx dalam menangani berbagai tugas pemrosesan teks yang kompleks. Namun, penting untuk diingat bahwa RegEx yang sangat kompleks dapat sulit dibaca dan di-maintain. Dalam beberapa kasus, mungkin lebih baik untuk memecah pola yang kompleks menjadi beberapa langkah atau menggunakan parser khusus untuk tugas-tugas tertentu seperti parsing HTML atau XML.


Tambahan example : 

  1. Penggunaan Lookahead dan Lookbehind:

Lookahead dan lookbehind adalah teknik yang powerful untuk mencocokkan pola berdasarkan konteks tanpa mengkonsumsi karakter dalam string.

python

import re def validate_password_complex(password): # Password harus memiliki 8-20 karakter, setidaknya satu huruf besar, # satu huruf kecil, satu angka, satu karakter khusus, dan tidak boleh # diawali atau diakhiri dengan karakter khusus. pattern = r'^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&])(?!.*[@$!%*?&]$)(?!^[@$!%*?&])[\w@$!%*?&]{8,20}$' return bool(re.match(pattern, password)) # Contoh penggunaan passwords = [ "Abc123!@#", "Weak", "NoSpecialChar123", "@StartWithSpecial123", "EndWithSpecial123@", "Valid1Password!", "TooLongPassword1234567!" ] for password in passwords: print(f"'{password}' is valid: {validate_password_complex(password)}")

Penjelasan:

  • (?=.*[A-Z]) adalah positive lookahead untuk huruf besar
  • (?=.*[a-z]) adalah positive lookahead untuk huruf kecil
  • (?=.*\d) adalah positive lookahead untuk angka
  • (?=.*[@$!%*?&]) adalah positive lookahead untuk karakter khusus
  • (?!.*[@$!%*?&]$) adalah negative lookahead untuk memastikan tidak diakhiri karakter khusus
  • (?!^[@$!%*?&]) adalah negative lookahead untuk memastikan tidak diawali karakter khusus
  1. Penggunaan Conditional Patterns:

RegEx memungkinkan penggunaan pola bersyarat berdasarkan kecocokan sebelumnya.

python

import re def parse_date(date_string): pattern = r'^(?:(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})|(?P<day2>\d{2})/(?P<month2>\d{2})/(?P<year2>\d{4}))$' match = re.match(pattern, date_string) if match: if match.group('year'): return { 'format': 'YYYY-MM-DD', 'year': match.group('year'), 'month': match.group('month'), 'day': match.group('day') } else: return { 'format': 'DD/MM/YYYY', 'year': match.group('year2'), 'month': match.group('month2'), 'day': match.group('day2') } return None # Contoh penggunaan dates = ['2024-03-15', '15/03/2024', '2024/03/15'] for date in dates: result = parse_date(date) print(f"Date: {date}, Parsed: {result}")

Penjelasan:

  • Pattern ini menggunakan conditional matching untuk mencocokkan dua format tanggal yang berbeda.
  • (?:...) digunakan untuk non-capturing groups.
  • Named groups digunakan untuk mengekstrak komponen tanggal.
  1. Recursive Patterns:

Python's re modul tidak mendukung recursive patterns secara langsung, tetapi kita bisa mensimulasikannya untuk kasus-kasus tertentu.

python

import re def match_nested_parentheses(text): pattern = r'\((?:[^()]|\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\))*\)' return re.findall(pattern, text) # Contoh penggunaan text = "This (is (a)) test (with (nested (parentheses)))" matches = match_nested_parentheses(text) print("Matched nested parentheses:", matches)

Penjelasan:

  • Pattern ini dapat mencocokkan tanda kurung bersarang hingga 3 level.
  • Untuk mencocokkan level yang lebih dalam, Anda perlu memperpanjang pola atau menggunakan pendekatan iteratif.
  1. Penggunaan RegEx dengan Pandas untuk Data Cleaning:
python

import pandas as pd import re # Membuat DataFrame contoh df = pd.DataFrame({ 'Name': ['John Doe', 'Jane Smith', 'Bob Johnson'], 'Email': ['john.doe@example.com', 'jane.smith@company.co.uk', 'bob123@gmail.com'], 'Phone': ['(123) 456-7890', '+1-987-654-3210', '555.123.4567'] }) # Fungsi untuk menormalisasi nomor telepon def normalize_phone(phone): # Menghapus semua karakter non-digit digits_only = re.sub(r'\D', '', phone) # Format menjadi XXX-XXX-XXXX return f"{digits_only[:3]}-{digits_only[3:6]}-{digits_only[6:]}" # Aplikasikan normalisasi ke kolom 'Phone' df['Normalized Phone'] = df['Phone'].apply(normalize_phone) # Ekstrak domain email df['Email Domain'] = df['Email'].str.extract(r'@(.+)$') print(df)

Penjelasan:

  • re.sub(r'\D', '', phone) menghapus semua karakter non-digit dari nomor telepon.
  • .str.extract(r'@(.+)$') mengekstrak domain email menggunakan metode pandas str.extract().
  1. Penggunaan Verbose RegEx:

Untuk pola yang sangat kompleks, penggunaan mode verbose dapat meningkatkan keterbacaan.

python

import re credit_card_pattern = re.compile(r''' ^(?: (?P<visa>4[0-9]{12}(?:[0-9]{3})?) | (?P<mastercard>5[1-5][0-9]{14}) | (?P<amex>3[47][0-9]{13}) | (?P<discover>6(?:011|5[0-9]{2})[0-9]{12}) )$ ''', re.VERBOSE) def validate_credit_card(number): number = re.sub(r'\D', '', number) # Remove non-digits match = credit_card_pattern.match(number) if match: return match.lastgroup return None # Contoh penggunaan cards = [ '4111111111111111', # Visa '5555555555554444', # Mastercard '378282246310005', # American Express '6011111111111117', # Discover '1234567890123456' # Invalid ] for card in cards: result = validate_credit_card(card) print(f"Card: {card}, Type: {result}")

Penjelasan:

  • re.VERBOSE memungkinkan kita menulis pola RegEx yang lebih mudah dibaca dengan komentar dan pemformatan.
  • Pattern ini mencocokkan dan mengidentifikasi berbagai jenis kartu kredit.
  • match.lastgroup mengembalikan nama grup yang cocok, yang sesuai dengan jenis kartu kredit.

Contoh-contoh ini mendemonstrasikan beberapa teknik lanjutan dalam penggunaan RegEx di Python. RegEx adalah alat yang sangat kuat untuk pemrosesan teks, tetapi perlu digunakan dengan hati-hati. Pola yang terlalu kompleks dapat sulit dipelihara dan mungkin memiliki implikasi performa. Selalu pertimbangkan trade-off antara kompleksitas RegEx dan kejelasan kode.


Tambahan contoh implentasi : 

  1. Parsing Log dengan Format Kompleks:

Misalkan kita memiliki log dengan format yang kompleks dan ingin mengekstrak informasi spesifik dari dalamnya.

python

import re from datetime import datetime log_pattern = re.compile(r''' (?P<timestamp>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2},\d{3})\s+ # Timestamp \[(?P<thread>[^\]]+)\]\s+ # Thread (?P<level>\w+)\s+ # Log level (?P<logger>[^\s]+)\s+-\s+ # Logger name (?P<message>.*?) # Log message (?:\s+\((?P<source_file>[^:]+):(?P<line_number>\d+)\))?$ # Source file and line number (optional) ''', re.VERBOSE) def parse_log_line(line): match = log_pattern.match(line) if match: data = match.groupdict() data['timestamp'] = datetime.strptime(data['timestamp'], '%Y-%m-%d %H:%M:%S,%f') data['line_number'] = int(data['line_number']) if data['line_number'] else None return data return None # Contoh penggunaan log_lines = [ "2024-03-15 10:23:45,123 [main] INFO com.example.App - Application started (App.java:42)", "2024-03-15 10:23:46,234 [worker-1] WARN com.example.Service - Connection timeout", "2024-03-15 10:23:47,345 [worker-2] ERROR com.example.Database - Query failed: SELECT * FROM users" ] for line in log_lines: parsed = parse_log_line(line) if parsed: print(f"Timestamp: {parsed['timestamp']}") print(f"Thread: {parsed['thread']}") print(f"Level: {parsed['level']}") print(f"Logger: {parsed['logger']}") print(f"Message: {parsed['message']}") print(f"Source: {parsed['source_file']}:{parsed['line_number']}") print("---")
  1. Validasi dan Normalisasi Alamat Email Kompleks:
python

import re email_pattern = re.compile(r''' (?P<local_part> (?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*) | (?:"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*") ) @ (?P<domain> (?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?) | (?:\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3} (?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-zA-Z0-9-]*[a-zA-Z0-9]: (?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+) \]) ) ''', re.VERBOSE) def validate_and_normalize_email(email): match = email_pattern.match(email) if match: local_part = match.group('local_part') domain = match.group('domain') # Normalize local part (remove quotes if unnecessary) if local_part.startswith('"') and local_part.endswith('"'): unquoted = local_part[1:-1] if email_pattern.match(f"{unquoted}@{domain}"): local_part = unquoted # Normalize domain to lowercase domain = domain.lower() return f"{local_part}@{domain}" return None # Contoh penggunaan emails = [ "user@example.com", "user+tag@example.com", '"very.unusual.@.unusual.com"@example.com', "admin@localhost", "user@[IPv6:2001:db8::1]", "invalid@email@example.com" ] for email in emails: normalized = validate_and_normalize_email(email) print(f"Original: {email}") print(f"Normalized: {normalized}") print("---")
  1. Parsing dan Validasi Expresi Matematika:
python

import re class ExpressionParser: def __init__(self): self.tokens = [] self.token_pattern = re.compile(r''' (?P<number>\d+(?:\.\d*)?) | (?P<operator>[+\-*/^]) | (?P<parenthesis>[\(\)]) ''', re.VERBOSE) def tokenize(self, expression): self.tokens = [] for match in self.token_pattern.finditer(expression): token = match.groupdict() token_type = next(k for k, v in token.items() if v is not None) self.tokens.append((token_type, match.group())) return self.tokens def validate(self): parenthesis_count = 0 last_token_type = None for token_type, value in self.tokens: if token_type == 'parenthesis': if value == '(': parenthesis_count += 1 else: parenthesis_count -= 1 if parenthesis_count < 0: return False if token_type == 'operator': if last_token_type in ['operator', None]: return False elif token_type == 'number': if last_token_type == 'number': return False last_token_type = token_type return parenthesis_count == 0 and last_token_type != 'operator' # Contoh penggunaan parser = ExpressionParser() expressions = [ "3 + 4 * 2 / ( 1 - 5 ) ^ 2", "3.14 + 2.0 * (7 - 3)", "1 + + 2", "((2 + 3) * 4", "5 +" ] for expr in expressions: tokens = parser.tokenize(expr) is_valid = parser.validate() print(f"Expression: {expr}") print(f"Tokens: {tokens}") print(f"Valid: {is_valid}") print("---")
  1. Ekstraksi dan Analisis Struktur HTML Kompleks:
python

import re from collections import defaultdict class HTMLAnalyzer: def __init__(self): self.tag_pattern = re.compile(r'<(?P<tag>[a-zA-Z0-9]+)(?P<attrs>[^>]*)>(?P<content>.*?)</(?P=tag)>', re.DOTALL) self.attr_pattern = re.compile(r'(?P<attr>[a-zA-Z0-9-]+)=["\'](.*?)["\']') def analyze(self, html): tags = defaultdict(int) attributes = defaultdict(lambda: defaultdict(int)) for match in self.tag_pattern.finditer(html): tag = match.group('tag') attrs = match.group('attrs') content = match.group('content') tags[tag] += 1 for attr_match in self.attr_pattern.finditer(attrs): attr = attr_match.group('attr') attributes[tag][attr] += 1 # Recursive analysis for nested content nested_tags, nested_attrs = self.analyze(content) for nested_tag, count in nested_tags.items(): tags[nested_tag] += count for nested_tag, nested_attr_dict in nested_attrs.items(): for nested_attr, nested_count in nested_attr_dict.items(): attributes[nested_tag][nested_attr] += nested_count return dict(tags), dict(attributes) # Contoh penggunaan html_content = """ <html> <head> <title>Example Page</title> <meta charset="UTF-8"> </head> <body> <div class="container"> <h1 id="main-title">Welcome</h1> <p>This is a <span class="highlight">sample</span> paragraph.</p> <ul> <li>Item 1</li> <li>Item 2</li> </ul> </div> </body> </html> """ analyzer = HTMLAnalyzer() tag_count, attribute_usage = analyzer.analyze(html_content) print("Tag Count:") for tag, count in tag_count.items(): print(f" {tag}: {count}") print("\nAttribute Usage:") for tag, attrs in attribute_usage.items(): print(f" {tag}:") for attr, count in attrs.items(): print(f" {attr}: {count}")

Contoh-contoh ini mendemonstrasikan penggunaan RegEx yang lebih kompleks dan canggih dalam Python untuk menangani berbagai tugas pemrosesan teks yang rumit. Mereka mencakup:

  1. Parsing log dengan format yang kompleks
  2. Validasi dan normalisasi alamat email sesuai dengan RFC 5322
  3. Parsing dan validasi ekspresi matematika
  4. Analisis struktur HTML yang kompleks

Perlu diingat bahwa meskipun RegEx sangat kuat, untuk beberapa tugas yang sangat kompleks (seperti parsing HTML atau XML yang lengkap), mungkin lebih baik menggunakan parser khusus atau library yang dirancang untuk tugas tersebut. RegEx sebaiknya digunakan dengan bijak, mempertimbangkan trade-off antara kompleksitas, kinerja, dan kemudahan pemeliharaan.


Comments

Popular posts from this blog

create image slider using phyton in web

Tahukah kamu Algoritma Genetika dan Penerapannya dalam Industri

create animated futuristic profile card using html+css+js

CRUD SPRING REACTIVE WEBFLUX +Mongo DB

Top 7 Digital Transformation Companies

100 perusahaan perangkat lunak (software) populer dari Eropa dan Amerika yang memiliki kehadiran atau operasional di Indonesia.

TOP 8 Framework Populer menggunakan bahasa .NET

Python Date and Time Manipulation

TOP 5 Trends Programming 2024

Daftar Kata Kunci (Keyword) dalam Bahasa Pemrograman Python