簡體   English   中英

在python 3中匹配和替換多個字符串的有效方法?

[英]Efficient way of matching and replacing multiple strings in python 3?

我有多個(> 30)編譯的正則表達式

regex_1 = re.compile(...)
regex_2 = re.compile(...)
#... define multiple regex's
regex_n = re.compile(...)

然后我有一個函數,它接受一個text並使用上面的每個正則表達式和re.sub方法替換它的一些單詞,如下所示

def sub_func(text):
    text = re.sub(regex_1, "string_1", text)
    # multiple subsitutions using all regex's ...
    text = re.sub(regex_n, "string_n", text)

    return text

問題:是否有更有效的方法來進行這些替換?

正則表達式不能從它們當前的形式推廣或簡化。

我覺得每次正則表達式每次重新分配時,每次正則表達式都會重新分配text的值,因為該函數只替換了整個text一兩個單詞。 此外,鑒於我必須為多個文檔執行此操作,這會使事情進一步減慢。

提前致謝!

重新分配值需要在Python中保持不變的時間。 與C語言不同,變量更像是“名稱標簽”。 因此,更改名稱標記指向的內容只需要很少的時間。

如果它們是常量字符串,我會將它們收集到一個元組中:

regexes = (
    (regex_1, 'string_1'),
    (regex_2, 'string_2'),
    (regex_3, 'string_3'),
    ...
)

然后在你的函數中,只需迭代列表:

def sub_func_2(text):
    for regex, sub in regexes:
        text = re.sub(regex, sub, text)
    return text

但是如果您的正則表達式實際上名為regex_1regex_2等,它們可能應該直接在某種列表中定義。

還要注意,如果你正在做'cat' - > 'dog'這樣的替換, str.replace()方法可能會更容易( text = text.replace('cat', 'dog') ),它可能會是快點。


如果你的字符串非常長,並且使用正則表達式重新制作它可能需要很長時間。 評論中提到的@Oliver Charlesworth方法的實現可能是:

# Instead of this:
regexes = (
   ('1(1)', '$1i'),
   ('2(2)(2)', '$1a$2'),
   ('(3)(3)3', '$1a$2')
)


# Merge the regexes:
regex = re.compile('(1(1))|(2(2)(2))|((3)(3)3)')
substitutions = (
    '{1}i', '{1}a{2}', '{1}a{2}'
)

# Keep track of how many groups are in each alternative
group_nos = (1, 2, 2)

cumulative = [1]
for i in group_nos:
    cumulative.append(cumulative[-1] + i + 1)
del i
cumulative = tuple(zip(substitutions, cumulative))

def _sub_func(match):
    iter_ = iter(cumulative)
    for sub, x in iter_:
        if match.group(x) is not None:
            return sub.format(*map(match.group, range(x, next(iter_)[1])))

def sub_func(text):
    return re.sub(regex, _sub_func, text)

但如果您有需要替換的重疊文本,則會出現故障。

我們可以將函數傳遞給re.sub repl參數

簡化為3個正則表達式以便於理解

假設regex_1,regex_2和regex_3分別為111,222和333。 然后,regex_replace將是按照regex_1,regex_2和regex_3的順序用於替換的列表保存字符串。

  • regex_1將取代'one'
  • regex_2替換為'two',依此類推

不知道這會改善運行時間,嘗試一下

import re
regex_x = re.compile('(111)|(222)|(333)')
regex_replace = ['one', 'two', 'three']

def sub_func(text):
    return re.sub(regex_x, lambda x:regex_replace[x.lastindex-1], text)

>>> sub_func('testing 111 222 333')
>>> 'testing one two three'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM