Trường hợp không nhạy cảm thay thế


Câu trả lời:


217

Các stringloại không hỗ trợ này. Có lẽ bạn tốt nhất nên sử dụng phương thức phụ biểu thức chính quy với tùy chọn re.IGNORECASE .

>>> import re
>>> insensitive_hippo = re.compile(re.escape('hippo'), re.IGNORECASE)
>>> insensitive_hippo.sub('giraffe', 'I want a hIPpo for my birthday')
'I want a giraffe for my birthday'

11
Nếu bạn chỉ thực hiện một thay thế duy nhất hoặc muốn lưu các dòng mã, sẽ hiệu quả hơn khi sử dụng một thay thế duy nhất với re.sub và cờ (? I): re.sub ('(? I)' + re .escape ('hà mã'), 'hươu cao cổ', 'Tôi muốn có một hIPpo cho ngày sinh nhật của tôi')
D Coetzee

3
Tại sao re.escape chỉ cho một chuỗi các chữ cái? Cảm ơn.
Elena

8
@Elena, nó không cần thiết 'hippo', nhưng sẽ hữu ích nếu giá trị thay thế được truyền vào một hàm, vì vậy nó thực sự là một ví dụ tốt hơn bất kỳ thứ gì khác.
Blair Conrad

2
Bên cạnh việc phải re.escapedùng kim của bạn, còn có một cái bẫy khác mà câu trả lời này không thể tránh được, được ghi chú trong stackoverflow.com/a/15831118/1709587 : kể từ khi re.subxử lý các chuỗi thoát, như đã lưu ý trong docs.python.org/l Library / re.html # re .sub , bạn cần thoát khỏi tất cả các dấu gạch chéo ngược trong chuỗi thay thế của bạn hoặc sử dụng lambda.
Đánh dấu Amery

84
import re
pattern = re.compile("hello", re.IGNORECASE)
pattern.sub("bye", "hello HeLLo HELLO")
# 'bye bye bye'

17
Hoặc một lớp lót: re.sub('hello', 'bye', 'hello HeLLo HELLO', flags=re.IGNORECASE)
Louis Yang

Lưu ý rằng re.subchỉ hỗ trợ cờ này kể từ Python 2.7.
fuenfundachtzig

47

Trong một dòng duy nhất:

import re
re.sub("(?i)hello","bye", "hello HeLLo HELLO") #'bye bye bye'
re.sub("(?i)he\.llo","bye", "he.llo He.LLo HE.LLO") #'bye bye bye'

Hoặc, sử dụng đối số "cờ" tùy chọn:

import re
re.sub("hello", "bye", "hello HeLLo HELLO", flags=re.I) #'bye bye bye'
re.sub("he\.llo", "bye", "he.llo He.LLo HE.LLO", flags=re.I) #'bye bye bye'

14

Tiếp tục câu trả lời của bFloch, chức năng này sẽ thay đổi không chỉ một mà là tất cả các lần xuất hiện cũ với mới - trong trường hợp không nhạy cảm.

def ireplace(old, new, text):
    idx = 0
    while idx < len(text):
        index_l = text.lower().find(old.lower(), idx)
        if index_l == -1:
            return text
        text = text[:index_l] + new + text[index_l + len(old):]
        idx = index_l + len(new) 
    return text

Làm rất tốt Tốt hơn nhiều so với regex; nó xử lý tất cả các loại ký tự, trong khi regex rất phức tạp về bất cứ thứ gì không phải là chữ và số. Câu trả lời ưa thích IMHO.
fyngyrz

Tất cả bạn phải làm là thoát khỏi regex: câu trả lời được chấp nhận ngắn hơn và dễ đọc hơn nhiều so với điều này.
Nhà vật lý điên

Escape chỉ hoạt động để khớp, dấu gạch chéo ngược ở đích có thể làm mọi thứ rối tung lên.
ideaman42

4

Giống như Blair Conrad nói string.replace không hỗ trợ điều này.

Sử dụng regex re.sub, nhưng nhớ thoát chuỗi thay thế trước. Lưu ý rằng không có tùy chọn cờ trong 2.6 cho re.sub, vì vậy bạn sẽ phải sử dụng công cụ sửa đổi được nhúng'(?i)' (hoặc đối tượng RE, xem câu trả lời của Blair Conrad). Ngoài ra, một cạm bẫy khác là phụ sẽ xử lý dấu gạch chéo ngược trong văn bản thay thế, nếu một chuỗi được đưa ra. Để tránh điều này thay vào đó có thể vượt qua trong lambda.

Đây là một chức năng:

import re
def ireplace(old, repl, text):
    return re.sub('(?i)'+re.escape(old), lambda m: repl, text)

>>> ireplace('hippo?', 'giraffe!?', 'You want a hiPPO?')
'You want a giraffe!?'
>>> ireplace(r'[binfolder]', r'C:\Temp\bin', r'[BinFolder]\test.exe')
'C:\\Temp\\bin\\test.exe'

4

Hàm này sử dụng cả hàm str.replace()re.findall()hàm. Nó sẽ thay thế tất cả các lần xuất hiện của patternstringvới replmột cách case-insensitive.

def replace_all(pattern, repl, string) -> str:
   occurences = re.findall(pattern, string, re.IGNORECASE)
   for occurence in occurences:
       string = string.replace(occurence, repl)
       return string

3

Điều này không yêu cầu thường xuyênExp

def ireplace(old, new, text):
    """ 
    Replace case insensitive
    Raises ValueError if string not found
    """
    index_l = text.lower().index(old.lower())
    return text[:index_l] + new + text[index_l + len(old):] 

3
Tốt, tuy nhiên điều này không thay đổi tất cả các lần xuất hiện cũ với mới, nhưng chỉ xảy ra lần đầu tiên.
rsmoorthy

5
Nó ít đọc hơn phiên bản regex. Không cần phải phát minh lại bánh xe ở đây.
Julian Bittner

Sẽ rất thú vị khi thực hiện một so sánh hiệu suất giữa phiên bản này và các phiên bản nâng cấp, nó có thể nhanh hơn, điều này quan trọng đối với một số ứng dụng. Hoặc nó có thể chậm hơn vì nó hoạt động nhiều hơn trong Python được giải thích.
D Coetzee

2

Một quan sát thú vị về chi tiết cú pháp và các tùy chọn:

Python 3.7.2 (tags / v3.7.2: 9a3ffc0492, ngày 23 tháng 12 năm 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] trên win32

import re
old = "TREEROOT treeroot TREerOot"
re.sub(r'(?i)treeroot', 'grassroot', old)

'cơ sở cơ sở'

re.sub(r'treeroot', 'grassroot', old)

'TREEROOT cơ sở TREerOot'

re.sub(r'treeroot', 'grassroot', old, flags=re.I)

'cơ sở cơ sở'

re.sub(r'treeroot', 'grassroot', old, re.I)

'TREEROOT cơ sở TREerOot'

Vì vậy, tiền tố (? I) trong biểu thức khớp hoặc thêm "flags = re.I" làm đối số thứ tư sẽ dẫn đến kết quả khớp không phân biệt chữ hoa chữ thường. NHƯNG, chỉ sử dụng "re.I" làm đối số thứ tư không dẫn đến kết quả khớp không phân biệt chữ hoa chữ thường.

Để so sánh,

re.findall(r'treeroot', old, re.I)

['TREEROOT', 'treeroot', 'TREerOot']

re.findall(r'treeroot', old)

['gốc cây']


Điều này không cung cấp một câu trả lời cho câu hỏi. vui lòng chỉnh sửa câu trả lời của bạn để đảm bảo rằng nó cải thiện các câu trả lời khác đã có trong câu hỏi này.
hongsy

1

Tôi đã được chuyển đổi thành các chuỗi thoát (cuộn xuống một chút), vì vậy tôi lưu ý rằng re.sub chuyển đổi các ký tự thoát bị gạch chéo ngược thành các chuỗi thoát.

Để ngăn chặn điều đó tôi đã viết như sau:

Thay thế trường hợp không nhạy cảm.

import re
    def ireplace(findtxt, replacetxt, data):
        return replacetxt.join(  re.compile(findtxt, flags=re.I).split(data)  )

Ngoài ra, nếu bạn muốn nó thay thế bằng các ký tự thoát, giống như các câu trả lời khác ở đây đang nhận được các ký tự bashslash có ý nghĩa đặc biệt được chuyển đổi thành chuỗi thoát, chỉ cần giải mã chuỗi tìm và thay thế chuỗi của bạn. Trong Python 3, có thể phải làm một cái gì đó như .decode ("unicode_escape") # python3

findtxt = findtxt.decode('string_escape') # python2
replacetxt = replacetxt.decode('string_escape') # python2
data = ireplace(findtxt, replacetxt, data)

Đã thử nghiệm trong Python 2.7.8

Mong rằng sẽ giúp.


0

chưa bao giờ đăng câu trả lời trước đây và chủ đề này thực sự cũ nhưng tôi đã đưa ra một câu hỏi khác và nhận ra tôi có thể nhận được phản hồi của bạn, tôi không dày dạn trong lập trình Python vì vậy nếu có những hạn chế đáng chú ý đối với nó, xin vui lòng chỉ ra vì nó học tốt: )

i='I want a hIPpo for my birthday'
key='hippo'
swp='giraffe'

o=(i.lower().split(key))
c=0
p=0
for w in o:
    o[c]=i[p:p+len(w)]
    p=p+len(key+w)
    c+=1
print(swp.join(o))

2
Đối với việc học: nói chung khi bạn thực hiện tìm kiếm và thay thế trên một chuỗi, tốt hơn hết là không phải biến nó thành một mảng trước tiên. Đó là lý do tại sao câu trả lời đầu tiên có lẽ là tốt nhất. Mặc dù nó đang sử dụng một mô-đun bên ngoài, nhưng nó lại coi chuỗi là một chuỗi. Nó cũng rõ ràng hơn một chút những gì đang xảy ra trong quá trình.
isaaclw

Đối với việc học: rất khó cho một nhà phát triển không có ngữ cảnh để đọc mã này và giải mã những gì nó đang làm :)
Todd
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.