Нежадні регекси Python


150

Як зробити так, щоб згенерований пітон був подібним "(.*)", якщо замість цього "a (b) c (d) e"відповідають збіги python ?"b""b) c (d"

Я знаю, що можу використовувати "[^)]"замість цього ".", але я шукаю більш загальне рішення, яке б моє регекс було трохи чистішим. Чи є якийсь спосіб сказати python "ей, відповідь якнайшвидше"?

Відповіді:


209

Ви шукаєте всесильних *?

З документів, Жадібний проти Нежадний

Ні-жадібні класифікатори *?, +?, ??або {m,n}?[...] матч , як маленький текст , наскільки це можливо.


За даними Інтернет-архіву, все, на що вказували посилання, - це копія документів модуля Python "re", тому посилання Трей працює так само добре.
spiffytech

2
яка загальна англійська назва для цього *??
Тревор Бойд Сміт

Wildcard символи @Trevor Бойд Сміт
Серж

3
Це називається "не жадібним" кваліфікатором
брунеттон

65
>>> x = "a (b) c (d) e"
>>> re.search(r"\(.*\)", x).group()
'(b) c (d)'
>>> re.search(r"\(.*?\)", x).group()
'(b)'

Згідно з документами :

Кваліфікатори ' *', ' +' і ' ?' всі жадібні; вони відповідають якомога більше тексту. Іноді така поведінка не бажана; якщо RE <.*>буде відповідати проти ' <H1>title</H1>', він відповідатиме всій рядку, а не лише ' <H1>'. Додавання " ?" після того, як класифікатор змушує проводити матч не жадібно або мінімально; якомога менше символів буде узгоджено. Використання .*?в попередньому виразі відповідатиме лише " <H1>".



5

Як говорили інші, використовуючи? модифікатор на кількісному показнику * вирішить вашу негайну проблему, але будьте обережні, ви починаєте блукати в області, де регулярні перерви перестають працювати і замість цього вам потрібен аналізатор. Наприклад, рядок "(foo (bar)) baz" викличе у вас проблеми.


5

Використання недоброзичливої ​​відповідності - це хороший початок, але я б також запропонував вам переглянути будь-яке використання .*- що з цим?

groups = re.search(r"\([^)]*\)", x)

3

Ви хочете, щоб він відповідав "(b)"? Зробіть так, як запропонували Zitrax і Paolo. Ви хочете, щоб це відповідало "b"? Зробіть

>>> x = "a (b) c (d) e"
>>> re.search(r"\((.*?)\)", x).group(1)
'b'

0

Для початку я не пропоную використовувати "*" у регулярних виразах. Так, я знаю, це найпоширеніший розділовий символ, але все-таки це погана ідея. Це тому, що, хоча це відповідає будь-якій кількості повторень для цього символу, "будь-який" включає 0, що, як правило, є те, для чого ви хочете викинути синтаксичну помилку, а не приймати. Натомість я пропоную використовувати +знак, який відповідає будь-якому повторюванню довжини> 1. Більше того, з того, що я бачу, ви маєте справу з виразками з фіксованою довжиною. Як результат, ви, ймовірно, можете використовувати {x, y}синтаксис, щоб конкретно вказати потрібну довжину.

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

?Коли це було сказано, я був би дуже обережний з тим, як це, як і викрутка Sonic у доктора. Хто має тенденцію робити, як я можу сказати, "злегка" небажані речі, якщо не ретельно відкалібровані. Наприклад, щоб використати ваш приклад, він визначить ((1)(відзначте відсутність другого rparen) як збіг.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.