Saya sedang melakukan "parser" yang harus mengganti kata kunci dengan kata kunci lain

trim(<something>)  --> ltrim(rtrim(<something>))

Saya menggunakan ekspresi reguler python. Masalah utamanya adalah karena di bagian <something> mungkin ada tanda kurung tambahan yang membuat pembentukan regex sangat sulit bagi saya. Cukup menambahkan ? untuk membuatnya tidak serakah tidak benar-benar berfungsi, dan menempatkan serakah regex akan cocok dengan tanda kurung di akhir file 200 baris ke bawah. Sejak awal saya menganggap orang lain memiliki masalah ini, dan saya menemukan dua pertanyaan ini.

Cara mengurai tanda kurung penutup dengan benar

Bagaimana cara menambahkan tanda kurung penutup yang hilang ke string dengan Python?

Tetapi tidak ada yang membantu dalam kasus saya, kode saya sejauh ini:

def run(path):
for root, dirs, files in os.walk(path):
    for fname in files:
        fpath = os.path.join(root, fname)
        with open(fpath, 'r') as f:
            s = f.read()
        s = s.replace("trim","ltrim(rtrim" )
        text = s
        text = re.sub(r'(\(.+(?!\))\b)', r"\1)", text)
        return text

Kode hanya menambahkan penutup ) tanpa menyertakan teks di antaranya meskipun saya menempatkan + di regex saya yang berarti setidaknya satu tampilan karakter apa pun.

Seperti ini

trim(p_name) menjadi ltrim(rtrim()p_name)

Saya membutuhkannya ltrim(rtrim(p_name))

3
Josip Juros 25 Mei 2021, 13:37

1 menjawab

Jawaban Terbaik

Anda tidak dapat mencocokkan pola rekursif dengan Python re bawaan, jadi Anda harus pip install regex untuk menginstal modul regex PyPi dan menggunakan

return regex.sub(r'\btrim(\((?:[^()]++|(?1))*\))', r'ltrim(r\g<0>)', text) )

Lihat demo regex.

Detail:

  • \btrim - cocok dengan seluruh kata trim
  • (\((?:[^()]++|(?1))*\)) - Grup 1:
    • \( - karakter (
    • (?:[^()]++|(?1))* - nol atau lebih karakter selain ( dan ) atau seluruh pola Grup 1 (berulang)
    • \) - karakter ).

Penggantinya adalah ltrim(r\g<0>): ltrim(r + seluruh pertandingan + ).

Lihat Python demo:

import regex
text = "trim(str(p_name))"
print( regex.sub(r'\btrim(\((?:[^()]++|(?1))*\))', r'ltrim(r\g<0>)', text) )
## => ltrim(rtrim(str(p_name)))
2
Wiktor Stribiżew 25 Mei 2021, 10:45