web-dev-qa-db-fra.com

Echec lors du filtrage de la liste de chaînes avec re.match

Je voudrais filtrer une liste de chaînes dans python en utilisant regex. Dans le cas suivant, ne gardez que les fichiers avec une extension '.npy'.

Le code qui ne fonctionne pas:

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)

La même expression rationnelle fonctionne pour moi dans Ruby:

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

Quel est le problème avec le code Python?

21
miluz
selected_files = filter(regex.match, files)

re.match('regex') est égal à re.search('^regex') ou text.startswith('regex') mais en version regex. Il vérifie uniquement si la chaîne commence par l'expression régulière .

Donc, utilisez re.search() à la place:

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)

Sortie:

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

Et si vous voulez juste obtenir tous les fichiers .npy, Utilisez simplement 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)
38
Kevin Guan

Il suffit d’utiliser search- car la correspondance commence à correspondre du début à la fin (c’est-à-dire la totalité) de la chaîne et la recherche correspond à n’importe où dans la chaîne.

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)

Sortie-

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

re.match() recherche une correspondance au début de la chaîne. Vous pouvez utiliser re.search() à la place.

2
Vlad

Si vous correspondez , le motif doit couvrir l’entrée entière . Soit vous prolongez l'expression régulière:

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

Ce qui correspondrait à:

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

Ou utilisez re.search , qui

balaye la chaîne à la recherche du premier emplacement où le modèle d'expression régulière produit une correspondance [...]

1
miku