Як використовувати змінну всередині регулярного виразу?


235

Я хотів би використовувати variableвнутрішню regex, як це можна зробити Python?

TEXTO = sys.argv[1]

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

9
Ви використовуєте струнове з'єднання
Кріс Еберл

Відповіді:


52

З python 3.6 ви також можете використовувати Literal String Interpolation , "f-string". У вашому конкретному випадку рішенням було б:

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

Редагувати:

Оскільки в коментарі виникли деякі запитання про те, як поводитися зі спеціальними символами, я хотів би продовжити свою відповідь:

необроблені рядки ('r'):

Одне з головних понять, яке ви повинні зрозуміти, працюючи зі спеціальними символами в регулярних виразах, - це розрізняти рядкові букви та регулярний вираз. Це дуже добре пояснено тут :

Коротко:

Скажімо, замість того, щоб знаходити межу слова \bпісля TEXTOтого, як ви хочете відповідати рядку \boundary. Ви повинні написати:

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

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

Це працює лише тому, що ми використовуємо необроблений рядок (регулярному вираженню передує 'r'), інакше ми повинні записати "\\\\ межа" в регулярний вираз (чотири зворотні косої риски). Крім того, без '\ r', \ b 'більше не перетворюється на межу слова, а на зворотну простір!

re.escape :

В основному ставить задню область перед будь-яким спеціальним символом. Отже, якщо ви очікуєте особливого символу в TEXTO, вам потрібно написати:

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

Примітка: Для будь-якої версії> = пітон 3.7 !, ", %, ', ,, /, :, ;, <, =, >, @, і `не втекли. Тільки спеціальні символи зі значенням у регулярному виразі все ще залишаються уникнутими. _не уникнути, оскільки Python 3.3. (s. тут )

Фігурні дужки:

Якщо ви хочете використовувати квантори в регулярному виразі за допомогою f-рядків, вам доведеться використовувати подвійні фігурні дужки. Скажімо, ви хочете відповідати TEXTO з наступними точно двома цифрами:

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

2
Станом на 2020 рік, це найпростіший і пітонічний спосіб використання змінної всередині регулярного виразу
CONvid19

3
Це, безумовно, WOW .
Гол Джейсона

2
хтось може пояснити значення "rf" тут
Харша Редді,

1
@HarshaReddy: 'r': Ця рядок є необробленою рядком: якщо ви не використовуєте її, '\ b' буде перетворений у символ зворотної області ( docs.python.org/3/howto/regex.html#more- зразок-сила ). 'f' повідомляє python, що це 'f-string', s. Посилання вище, і дозволяє записати змінну в фігурні дужки-
повітряна

2
Як написати кількісні показники у f-рядках: fr"foo{{1,5}}"(подвійні дужки)
PunchyRascal

281

Ви повинні побудувати регулярний вираз як рядок:

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

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

Зверніть увагу на використання re.escapeтак, що якщо у вашому тексті є спеціальні символи, вони не будуть інтерпретуватися як такі.


4
Що робити, якщо ваша змінна буде першою? r'' + foo + 'bar'?
deed02392

@ deed02392 r''не потрібно, якщо ви це робите re.escape(foo), що вам все одно слід. Насправді, я думаю, reінтерпретує все, що це дано, як рядок unicode, незалежно від того, ви префікс rчи ні.
OJFord

Чи працює .format () на місці re.escape чи потрібен re.escape ()?
Праксителес

@praxiteles ти знайшов відповідь?
CONvid19

2
Я не впевнений, чи це працює в мені, я повинен мати групу, частиною якої є змінна. Інші відповіді нижче виглядають більш інтуїтивно для цього, і не розбивайте регулярний вираз на кілька виразів.
відвід

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

Це вставить те, що є в TEXTO, в регулярний вираз у вигляді рядка.



6

Мені здається дуже зручним побудувати шаблон регулярного вираження, поєднуючи разом кілька менших шаблонів.

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)

Вихід:

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

4

Я погоджуюся з усім вищезазначеним, якщо:

sys.argv[1] було щось подібне Chicken\d{2}-\d{2}An\s*important\s*anchor

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

ви б не хотіли використовувати re.escape, тому що в такому випадку ви хочете, щоб він поводився як регулярний вираз

TEXTO = sys.argv[1]

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

2

Мені потрібно було шукати схожі між собою імена користувачів, і те, що сказав Нед Батчелдер, було неймовірно корисним. Однак я виявив, що у мене був більш чистий вихід, коли я використовував re.compile для створення свого пошукового терміна:

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

Вихід може бути надрукований за допомогою наступного:

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

ви можете спробувати інше використання, використовуючи formatграммер сугер:

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

0

Ви також можете використовувати ключове слово формату для цього. Метод Format замінить {} заповнення місця на змінну, яку ви передали методу формату як аргумент.

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

0

більше приклад

У мене configus.yml з файлами потоків

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

в коді python, який я використовую

data_time_real_file=re.findall(r""+flows[flow]["pattern"][0]+"", latest_file)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.