Трябва да намеря всички съвпадения в низ за даден регрекс. Използвах 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+)*")
Някои причини, поради които е по-добре:
(?:...)
е група, която не е заснемане, така че получавате само един резултат за всяко съвпадение.d+(?:,d+)*
е по-добър regex, по-ефективен и по-малко вероятно да върне фалшиви положителни резултати.Винаги трябва да използвате необработените низове на Python за regexes, ако е възможно; по-малко вероятно е да се изненадате от изходните последователности на regex (като
b
за границата на думите) се интерпретират като последователности от последователни букви (като напримерb
за Backspace).