Re.findall: примеры (PYTHON)

Полное руководство по функции findall для поиска в Python
Раздел: Регулярные выражения, Поиск
re.findall(pattern, string, flags): list

Описание функции re.findall

Функция findall из модуля re используется для поиска всех непересекающихся соответствий шаблону регулярного выражения в строке. Она возвращает список строк или кортежей, в зависимости от наличия групп в шаблоне.

Использование функции целесообразно при необходимости извлечения всех фрагментов текста, соответствующих заданному шаблону. Например, это может быть поиск всех email-адресов, хештегов или числовых значений в документе.

Аргументы функции

  • pattern (обязательный): строка или скомпилированное регулярное выражение (объект Pattern).
  • string (обязательный): строка, в которой осуществляется поиск.
  • flags (опциональный): один или несколько флагов, изменяющих поведение регулярного выражения. Например, re.IGNORECASE для регистронезависимого поиска.

Возвращаемое значение

  • Если в шаблоне нет групп, возвращается список строк, соответствующих всему шаблону.
  • Если в шаблоне есть одна группа, возвращается список строк, соответствующих этой группе.
  • Если групп несколько, возвращается список кортежей, каждый из которых содержит строки, соответствующие группам.
  • При отсутствии совпадений возвращается пустой список.

Примеры использования re.findall

Простейший пример поиска всех чисел в строке:

import re
text = 'В 2024 году было 12 месяцев и 365 дней.'
result = re.findall(r'\d+', text)
print(result)
['2024', '12', '365']

Использование флага для регистронезависимого поиска:

result = re.findall(r'python', 'Python is python', flags=re.IGNORECASE)
print(result)
['Python', 'python']

Работа с группами. Поиск пар 'ключ=значение':

text = 'width=200 height=300'
result = re.findall(r'(\w+)=(\d+)', text)
print(result)
[('width', '200'), ('height', '300')]

Использование скомпилированного регулярного выражения:

pattern = re.compile(r'#[0-9a-fA-F]{6}')
colors = pattern.findall('Цвета: #ff0000, #00ff00, #0000ff')
print(colors)
['#ff0000', '#00ff00', '#0000ff']

Похожие функции в Python

Модуль re предлагает несколько функций для поиска по шаблону.

re.finditer

Функция finditer возвращает итератор с объектами Match для каждого совпадения. Ее использование предпочтительнее при обработке больших текстов, так как не загружает все результаты в память сразу. Также она предоставляет полную информацию о позиции каждого совпадения.

re.search

Функция search находит только первое совпадение в строке и возвращает объект Match или None. Используется, когда нужно проверить наличие шаблона и получить детали по первому совпадению.

re.match

Функция match ищет совпадение только в начале строки. Ее применение логично для проверки формата строк, например, при валидации ввода.

re.fullmatch

Функция fullmatch требует, чтобы вся строка целиком соответствовала шаблону. Это удобно для строгой проверки данных на соответствие шаблону.

Выбор функции зависит от задачи: findall - для извлечения всех фрагментов, finditer - для пошаговой обработки, search/match - для проверки наличия.

Типичные ошибки

Неверная интерпретация возвращаемого значения при наличии групп

Наличие групп в шаблоне меняет формат результата, что иногда приводит к неожиданностям.

import re
# Ожидание списка полных совпадений, но в шаблоне есть группа.
result = re.findall(r'(\d+)', 'abc123def')
print(result)
['123']

Здесь возвращается список строк, соответствующих группе, а не всему шаблону.

Использование жадных квантификаторов, приводящее к пропуску совпадений

Жадные квантификаторы захватывают максимально возможное количество символов, что может объединять несколько нужных фрагментов в один.

text = '"one" "two" "three"'
result = re.findall(r'".*"', text)
print(result)
['"one" "two" "three"']

Для поиска отдельных цитат следует использовать нежадный квантификатор .*?.

Ошибки из-за специальных символов в строке шаблона

Символы, такие как обратная косая черта, требуют экранирования как в строковом литерале Python, так и в синтаксисе регулярных выражений.

# Ошибка: попытка найти обратную косую черту.
# Неправильно:
try:
    re.findall('\', 'text')
except re.error as e:
    print(e)
bad escape \ at position 0

Правильно использовать сырые строки: r'\\'.

Смешение строк и байтов

Попытка использовать байтовые строки с шаблоном в виде обычной строки вызывает ошибку.

# Неправильно:
try:
    re.findall(r'\d+', b'123')
except TypeError as e:
    print(e)
cannot use a string pattern on a bytes-like object

Для байтовых строк шаблон также должен быть байтовым: re.findall(b'\\d+', b'123').

Изменения в последних версиях Python

В Python 3.7 была добавлена поддержка флага re.ASCII по умолчанию для строковых шаблонов, скомпилированных с флагом re.A. Это делает поведение регулярных выражений более последовательным.

В Python 3.11 функция re.findall стала работать быстрее для некоторых типов шаблонов благодаря внутренним оптимизациям механизма регулярных выражений.

Начиная с Python 3.6, шаблоны в формате строк с вставленными нулевыми байтами больше не допускаются и вызывают предупреждение DeprecationWarning, а в Python 3.11 - ошибку.

В Python 3.14 планируются дальнейшие улучшения производительности.

Расширенные примеры

Извлечение данных из структурированного текста, например, лог-файла.

Пример python
log = """
[ERROR] 2023-10-05 10:15:23 Connection failed
[INFO] 2023-10-05 10:15:25 Retrying...
[ERROR] 2023-10-05 10:15:30 Timeout
"""
# Извлечение уровней логов и сообщений
entries = re.findall(r'\[(\w+)\] (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (.+)', log)
for level, timestamp, message in entries:
    print(f'{level} at {timestamp}: {message}')
ERROR at 2023-10-05 10:15:23: Connection failed
INFO at 2023-10-05 10:15:25: Retrying...
ERROR at 2023-10-05 10:15:30: Timeout

Поиск всех слов, начинающихся с заглавной буквы (поиск имен собственных).

Пример python
text = 'В Москве и Париже живут люди.'
result = re.findall(r'\b[А-ЯЁA-Z][а-яёa-z]*\b', text)
print(result)
['Москве', 'Париже']

Использование просмотра вперед и назад для поиска с контекстом.

Пример python
# Найти числа, после которых стоит 'px'
text = 'width: 200px, height: 300px, depth: 400cm'
result = re.findall(r'\d+(?=px)', text)
print(result)
['200', '300']

Обработка многострочного текста с флагом re.MULTILINE.

Пример python
text = """
Name: John
Age: 30
City: NY
Name: Anna
Age: 25
"""
# Извлечь все значения после 'Age:'
ages = re.findall(r'^Age: (\d+)$', text, flags=re.MULTILINE)
print(ages)
['30', '25']

Работа с повторяющимися группами. Поиск всех пар тегов в HTML-подобной строке.

Пример python
html = '
test
sample
another
' tags = re.findall(r'<([a-z]+)>(.*?)', html) print(tags)
[('div', 'test'), ('span', 'sample'), ('div', 'another')]

Извлечение данных с перекрывающимися совпадениями с использованием позитивного просмотра вперед.

Пример python
# Найти все перекрывающиеся подстроки 'aba' в строке 'ababa'
text = 'ababa'
result = re.findall(r'(?=(aba))', text)
print(result)
['aba', 'aba']

Аналоги функции в других языках

JavaScript

Метод String.prototype.match с глобальным флагом g возвращает массив всех совпадений. Если в регулярном выражении есть группы, они тоже включаются в результат.

let text = 'a1 b2 c3';
let result = text.match(/\w\d/g);
console.log(result);
['a1', 'b2', 'c3']

PHP

Функция preg_match_all выполняет глобальный поиск по шаблону. Результат помещается в массив, структура которого зависит от флагов.

$text = 'a1 b2 c3';
preg_match_all('/\w\d/', $text, $matches);
print_r($matches[0]);
Array
(
    [0] => a1
    [1] => b2
    [2] => c3
)

Java

Класс Matcher используется для поиска. Для получения всех результатов применяется цикл с методом find.

import java.util.regex.*;
Pattern p = Pattern.compile("\\w\\d");
Matcher m = p.matcher("a1 b2 c3");
while (m.find()) {
    System.out.println(m.group());
}
a1
b2
c3

C#

Метод Regex.Matches возвращает коллекцию объектов Match.

using System.Text.RegularExpressions;
var matches = Regex.Matches("a1 b2 c3", @"\w\d");
foreach (Match m in matches) Console.WriteLine(m.Value);
a1
b2
c3

Golang

Метод FindAllString у типа Regexp возвращает срез строк. В отличие от Python, группы не выделяются отдельно в этом методе.

package main
import (
    "fmt"
    "regexp"
)
func main() {
    re := regexp.MustCompile(`\w\d`)
    result := re.FindAllString("a1 b2 c3", -1)
    fmt.Println(result)
}
[a1 b2 c3]

Kotlin

Метод findAll у объекта Regex возвращает последовательность результатов.

val text = "a1 b2 c3"
val result = Regex("\\w\\d").findAll(text).map { it.value }.toList()
println(result)
[a1, b2, c3]

Lua

Функция string.gmatch возвращает итератор для всех совпадений.

for match in string.gmatch("a1 b2 c3", "%w%d") do
    print(match)
end
a1
b2
c3

SQL (PostgreSQL)

Функция regexp_matches возвращает множество строк с массивами совпадений. Работает в контексте запроса.

SELECT regexp_matches('a1 b2 c3', '\w\d', 'g');
{a1}
{b2}
{c3}

Основные отличия от Python: способ возврата данных (массивы, итераторы, коллекции), синтаксис регулярных выражений и обработка групп.

питон re.findall function comments

En
Re.findall Find all pattern matches in string