Ошибка при фильтрации списка строк с помощью re.match

Я хотел бы отфильтровать список строк в python с помощью regex. В следующем случае сохраняются только файлы с расширением ".npy".

Код, который не работает:

import re

files = [ '/a/b/c/la_seg_x005_y003.png',
          '/a/b/c/la_seg_x005_y003.npy',
          '/a/b/c/la_seg_x004_y003.png',
          '/a/b/c/la_seg_x004_y003.npy',
          '/a/b/c/la_seg_x003_y003.png',
          '/a/b/c/la_seg_x003_y003.npy', ]

regex = re.compile(r'_x\d+_y\d+\.npy')

selected_files = filter(regex.match, files)
print(selected_files)

Это же регулярное выражение работает для меня в Ruby:

selected = files.select { |f| f =~ /_x\d+_y\d+\.npy/ }

Что не так с кодом Python?

Ответ 1

selected_files = filter(regex.match, files)

re.match('regex') невероятно похож на re.search('^regex') или text.startswith('regex'), но имеет регулярное выражение. Он только проверяет, начинается ли строка с регулярного выражения.

Поэтому вместо этого используйте re.search():

import re

files = [ '/a/b/c/la_seg_x005_y003.png',
          '/a/b/c/la_seg_x005_y003.npy',
          '/a/b/c/la_seg_x004_y003.png',
          '/a/b/c/la_seg_x004_y003.npy',
          '/a/b/c/la_seg_x003_y003.png',
          '/a/b/c/la_seg_x003_y003.npy', ]

regex = re.compile(r'_x\d+_y\d+\.npy')

selected_files = list(filter(regex.search, files))
# The list call is only required in Python 3, since filter was changed to return a generator
print(selected_files)

Выход:

['/a/b/c/la_seg_x005_y003.npy',
 '/a/b/c/la_seg_x004_y003.npy',
 '/a/b/c/la_seg_x003_y003.npy']

И если вы просто хотите получить все файлы .npy, просто используйте str.endswith():

files = [ '/a/b/c/la_seg_x005_y003.png',
          '/a/b/c/la_seg_x005_y003.npy',
          '/a/b/c/la_seg_x004_y003.png',
          '/a/b/c/la_seg_x004_y003.npy',
          '/a/b/c/la_seg_x003_y003.png',
          '/a/b/c/la_seg_x003_y003.npy', ]


selected_files = list(filter(lambda x: x.endswith('.npy'), files))

print(selected_files)

Ответ 2

Просто используйте search - поскольку совпадение начинается с начала от начала до конца (т.е. Целого) строки и поиска в любом месте строки.

import re

files = [ '/a/b/c/la_seg_x005_y003.png',
          '/a/b/c/la_seg_x005_y003.npy',
          '/a/b/c/la_seg_x004_y003.png',
          '/a/b/c/la_seg_x004_y003.npy',
          '/a/b/c/la_seg_x003_y003.png',
          '/a/b/c/la_seg_x003_y003.npy', ]

regex = re.compile(r'_x\d+_y\d+\.npy')

selected_files = filter(regex.search, files)
print(selected_files)

Output-

['/a/b/c/la_seg_x005_y003.npy', '/a/b/c/la_seg_x004_y003.npy', '/a/b/c/la_seg_x003_y003.npy']

Ответ 3

re.match() ищет совпадение в начале строки. re.search() этого вы можете использовать re.search().

Ответ 4

Если вы соответствуете, шаблон должен охватывать весь вход. Либо расширяйте регулярное выражение:

regex = re.compile(r'.*_x\d+_y\d+\.npy')

Что бы соответствовало:

['/a/b/c/la_seg_x005_y003.npy',
 '/a/b/c/la_seg_x004_y003.npy',
 '/a/b/c/la_seg_x003_y003.npy']

Или используйте re.search, который

просматривает строку, которая ищет первое место, где шаблон регулярного выражения создает совпадение [...]