/ / python - търсене и намиране на regex - python, regex, search, string-matching, findall

python - regex търсене и търсене - python, regex, search, string-matching, findall

Трябва да намеря всички съвпадения в низ за даден регрекс. Използвах findall() да направя това, докато не се натъкнах на случай, в който не правеше това, което очаквах.

regex = re.compile("(d+,?)+")
s = "There are 9,000,000 bicycles in Beijing."

print re.search(regex, s).group(0)
> 9,000,000

print re.findall(regex, s)
> ["000"]

В такъв случай search() връща това, което ми трябва (най-дългия мач), но findall() се държи по различен начин, въпреки че документите предполагат, че трябва да бъде същото:

findall() съвпада с всички събития на шаблон, а не само с първия като search() прави.

  • Защо поведението е различно?

  • Как мога да постигна резултат search() с findall() (или нещо друго)?

Отговори:

16 за отговор № 1

Добре, виждам какво се случва ... от документите:

Ако в шаблона присъстват една или повече групи, върнете списък от групи; това ще бъде списък с кортежи, ако шаблонът има повече от една група.

Както се оказва, имате група, "(d +,?)" ... така че това, което се връща е последната поява на тази група, или 000.

Едно от решенията е да обградите цялото regex от група, като тази

regex = re.compile("((d+,?)+)")

тогава ще се върне [("9,000,000", "000")], което е кортеж, съдържащ двете групи. разбира се, вие се интересувате само от първата.

Лично аз ще използвам следните regex

regex = re.compile("((d+,)*d+)")

за да избегнем съвпадение на неща като „това е лош номер 9,123“,

Редактиране.

Ето един начин да избегнете необходимостта от заобикаляне на израза чрез скоби или да се справите с кортежи

s = "..."
regex = re.compile("(d+,?)+")
it = re.finditer(regex, s)

for match in it:
print match.group(0)

finditer връща итератор, който можете да използвате за достъп до всички намерени съвпадения. тези съвпадащи обекти са същите, които се връщат с re.search, така че група (0) връща резултата, който очаквате.


7 за отговор № 2

@aleph_null "S отговор правилно обяснява какво причинява проблема ви, но мисля, че имам по-добро решение. Използвайте този regex:

regex = re.compile(r"d+(?:,d+)*")

Някои причини, поради които е по-добре:

  1. (?:...) е група, която не е заснемане, така че получавате само един резултат за всяко съвпадение.

  2. d+(?:,d+)* е по-добър regex, по-ефективен и по-малко вероятно да върне фалшиви положителни резултати.

  3. Винаги трябва да използвате необработените низове на Python за regexes, ако е възможно; по-малко вероятно е да се изненадате от изходните последователности на regex (като b за границата на думите) се интерпретират като последователности от последователни букви (като например b за Backspace).