Làm thế nào để sử dụng một biến trong một biểu thức chính quy?


235

Tôi muốn sử dụng một variablebên trong a regex, làm thế nào tôi có thể làm điều này trong Python?

TEXTO = sys.argv[1]

if re.search(r"\b(?=\w)TEXTO\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed

9
Bạn sử dụng nối chuỗi
Chris Eberle

Câu trả lời:


52

Từ python 3.6 trở đi, bạn cũng có thể sử dụng Nội suy chuỗi ký tự , "chuỗi f". Trong trường hợp cụ thể của bạn, giải pháp sẽ là:

if re.search(rf"\b(?=\w){TEXTO}\b(?!\w)", subject, re.IGNORECASE):
    ...do something

BIÊN TẬP:

Vì đã có một số câu hỏi trong nhận xét về cách đối phó với các nhân vật đặc biệt mà tôi muốn mở rộng câu trả lời của mình:

chuỗi thô ('r'):

Một trong những khái niệm chính bạn phải hiểu khi xử lý các ký tự đặc biệt trong các biểu thức chính quy là phân biệt giữa các chuỗi ký tự và chính biểu thức chính quy. Nó được giải thích rất tốt ở đây :

Nói ngắn gọn:

Hãy nói thay vì tìm một ranh giới từ \bsau khi TEXTObạn muốn khớp chuỗi \boundary. Bạn phải viết:

TEXTO = "Var"
subject = r"Var\boundary"

if re.search(rf"\b(?=\w){TEXTO}\\boundary(?!\w)", subject, re.IGNORECASE):
    print("match")

Điều này chỉ hoạt động bởi vì chúng tôi đang sử dụng một chuỗi thô (biểu thức chính được đặt trước 'r'), nếu không, chúng tôi phải viết "ranh giới" trong biểu thức chính (bốn dấu gạch chéo ngược). Ngoài ra, không có '\ r', \ b 'sẽ không chuyển đổi thành ranh giới từ nữa mà trở thành khoảng lùi!

tái hiện :

Về cơ bản đặt một khoảng lùi trước bất kỳ ký tự đặc biệt nào. Do đó, nếu bạn mong đợi một ký tự đặc biệt trong TEXTO, bạn cần viết:

if re.search(rf"\b(?=\w){re.escape(TEXTO)}\b(?!\w)", subject, re.IGNORECASE):
    print("match")

LƯU Ý: Đối với bất kỳ phiên bản> = python 3.7: !, ", %, ', ,, /, :, ;, <, =, >, @, và `không thoát. Chỉ những nhân vật đặc biệt có ý nghĩa trong một regex vẫn được thoát. _không thoát được kể từ Python 3.3. (s. ở đây )

Dấu ngoặc nhọn:

Nếu bạn muốn sử dụng bộ định lượng trong biểu thức chính quy bằng chuỗi f, bạn phải sử dụng dấu ngoặc nhọn. Giả sử bạn muốn khớp TEXTO theo sau với đúng 2 chữ số:

if re.search(rf"\b(?=\w){re.escape(TEXTO)}\d{{2}}\b(?!\w)", subject, re.IGNORECASE):
    print("match")

2
Kể từ năm 2020, đây là cách đơn giản nhất và dễ sử dụng nhất trong một biểu thức chính quy
CONvid19

3
Đây chắc chắn là một WOW .
Mục tiêu Jason

2
ai đó có thể giải thích tầm quan trọng của "rf" ở đây không
Harsha Reddy

1
@HarshaReddy: 'r': Chuỗi này là một chuỗi thô: Nếu bạn không sử dụng nó, '\ b' sẽ được chuyển đổi thành ký tự backspace ( docs.python.org/3/howto/regex.html#more- mô hình-sức mạnh ). 'f' nói với python rằng đây là 'f-string', s. liên kết ở trên và cho phép bạn viết biến vào dấu ngoặc nhọn-
trên không vào

2
Cách viết bộ định lượng trong chuỗi f: fr"foo{{1,5}}"(nhân đôi số niềng răng)
PunchyRascal

281

Bạn phải xây dựng regex dưới dạng chuỗi:

TEXTO = sys.argv[1]
my_regex = r"\b(?=\w)" + re.escape(TEXTO) + r"\b(?!\w)"

if re.search(my_regex, subject, re.IGNORECASE):
    etc.

Lưu ý việc sử dụng re.escapeđể nếu văn bản của bạn có các ký tự đặc biệt, chúng sẽ không được hiểu như vậy.


4
Điều gì xảy ra nếu biến của bạn đi trước? r'' + foo + 'bar'?
deed02392

@ deed02392 r''không cần thiết nếu bạn làm re.escape(foo), dù sao bạn cũng nên. Trên thực tế, tôi nghĩ rằng rediễn giải bất cứ điều gì nó được đưa ra dưới dạng một chuỗi unicode bất kể bạn có tiền tố rhay không.
OJFord

Liệu .format () có hoạt động tốt thay cho re.escape hay re.escape () cần thiết không?
Praxlistes

@praxiteles bạn đã tìm được câu trả lời chưa?
CONvid19

2
Tôi không chắc chắn nếu điều này hoạt động trong tôi cần phải có một nhóm trong đó biến là một phần của. Các câu trả lời khác bên dưới có vẻ trực quan hơn cho điều đó và đừng chia regex thành nhiều biểu thức.
guival

48
if re.search(r"\b(?<=\w)%s\b(?!\w)" % TEXTO, subject, re.IGNORECASE):

Điều này sẽ chèn những gì trong TEXTO vào regex dưới dạng chuỗi.



6

Tôi thấy rất thuận tiện để xây dựng một mẫu biểu thức chính quy bằng cách xâu chuỗi nhiều mẫu nhỏ hơn lại với nhau.

import re

string = "begin:id1:tag:middl:id2:tag:id3:end"
re_str1 = r'(?<=(\S{5})):'
re_str2 = r'(id\d+):(?=tag:)'
re_pattern = re.compile(re_str1 + re_str2)
match = re_pattern.findall(string)
print(match)

Đầu ra:

[('begin', 'id1'), ('middl', 'id2')]

4

Tôi đồng ý với tất cả những điều trên trừ khi:

sys.argv[1] giống như Chicken\d{2}-\d{2}An\s*important\s*anchor

sys.argv[1] = "Chicken\d{2}-\d{2}An\s*important\s*anchor"

bạn sẽ không muốn sử dụng re.escape, vì trong trường hợp đó bạn muốn nó hoạt động như một regex

TEXTO = sys.argv[1]

if re.search(r"\b(?<=\w)" + TEXTO + "\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed

2

Tôi cần tìm kiếm những tên người dùng giống nhau và những gì Ned Batchelder nói là vô cùng hữu ích. Tuy nhiên, tôi thấy tôi có đầu ra sạch hơn khi tôi sử dụng re.compile để tạo cụm từ tìm kiếm lại:

pattern = re.compile(r"("+username+".*):(.*?):(.*?):(.*?):(.*)"
matches = re.findall(pattern, lines)

Đầu ra có thể được in bằng cách sử dụng như sau:

print(matches[1]) # prints one whole matching line (in this case, the first line)
print(matches[1][3]) # prints the fourth character group (established with the parentheses in the regex statement) of the first line.

1

bạn có thể thử cách sử dụng khác bằng cách sử dụng trình tạo formatngữ pháp:

re_genre = r'{}'.format(your_variable)
regex_pattern = re.compile(re_genre)  

0

Bạn cũng có thể sử dụng từ khóa định dạng cho phương thức.Format này sẽ thay thế {} giữ chỗ cho biến mà bạn đã truyền cho phương thức định dạng làm đối số.

if re.search(r"\b(?=\w)**{}**\b(?!\w)".**format(TEXTO)**, subject, re.IGNORECASE):
    # Successful match**strong text**
else:
    # Match attempt failed

0

ví dụ khác

Tôi có configus.yml với các tệp

"pattern":
  - _(\d{14})_
"datetime_string":
  - "%m%d%Y%H%M%f"

trong mã python tôi sử dụng

data_time_real_file=re.findall(r""+flows[flow]["pattern"][0]+"", latest_file)
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.