regulares python3 online expresiones ejemplos abder python regex

python3 - Descubre la cantidad de grupos de captura en las expresiones regulares de Python



python string expresiones regulares (7)

¿Hay alguna forma de determinar cuántos grupos de captura hay en una expresión regular determinada?

Me gustaría poder hacer lo siguiente:

def groups(regexp, s): """ Returns the first result of re.findall, or an empty default >>> groups(r''(/d)(/d)(/d)'', ''123'') (''1'', ''2'', ''3'') >>> groups(r''(/d)(/d)(/d)'', ''abc'') ('''', '''', '''') """ import re m = re.search(regexp, s) if m: return m.groups() return ('''',) * num_of_groups(regexp)

Esto me permite hacer cosas como estas:

first, last, phone = groups(r''(/w+) (/w+) ([/d/-]+)'', ''John Doe 555-3456'')

Sin embargo, no sé cómo implementar num_of_groups . (Actualmente solo trabajo alrededor.)

EDITAR: Siguiendo el consejo de rslite , reemplacé re.findall con re.search .

sre_parse parece ser la solución más robusta y completa, pero requiere cruzar árboles y parece ser un poco pesado.

La expresión regular de MizardX parece cubrir todas las bases, así que voy a ir con eso.


Algo de inside sre_parse podría ayudar.

A primera vista, tal vez algo como:

>>> import sre_parse >>> sre_parse.parse(''(/d)/d(/d)'') [(''subpattern'', (1, [(''in'', [(''category'', ''category_digit'')])])), (''in'', [(''category'', ''category_digit'')]), (''subpattern'', (2, [(''in'', [(''category'', ''category_digit'')])]))]

Es decir, los elementos de tipo ''subpatrón'':

import sre_parse def count_patterns(regex): """ >>> count_patterns(''foo: /d'') 0 >>> count_patterns(''foo: (/d)'') 1 >>> count_patterns(''foo: (/d(/s))'') 1 """ parsed = sre_parse.parse(regex) return len([token for token in parsed if token[0] == ''subpattern''])

Tenga en cuenta que solo estamos contando los patrones de nivel de raíz aquí, por lo que el último ejemplo solo devuelve 1. Para cambiar esto, los tokens deberían buscarse recursivamente.


En primer lugar, si solo necesita el primer resultado de re.findall, es mejor usar re.search que devuelva una coincidencia o None.

Para el número de grupos, puede contar el número de paréntesis abiertos ''('' excepto los que se han escapado con ''/'. Puede usar otra expresión regular para eso:

def num_of_groups(regexp): rg = re.compile(r''(?<!//)/('') return len(rg.findall(regexp))

Tenga en cuenta que esto no funciona si la expresión regular contiene grupos que no capturan y también si ''('' se escapó usándolo como ''[(]''. Así que esto no es muy confiable. Pero dependiendo de las expresiones regulares que use, podría ayuda.



Podría estar equivocado, pero no creo que haya una manera de encontrar la cantidad de grupos que se habrían devuelto si la expresión regular hubiera coincidido. La única forma en que puedo pensar para hacer que esto funcione de la manera que quieres es pasar el número de coincidencias que tu expresión regular particular espera como argumento.

Sin embargo, para aclarar: cuando findall tiene éxito, ¿solo quiere que se devuelva la primera coincidencia, pero cuando falla, quiere una lista de cadenas vacías? Porque el comentario parece mostrar todas las coincidencias que se devuelven como una lista.


Usando su código como base:

def groups(regexp, s): """ Returns the first result of re.findall, or an empty default >>> groups(r''(/d)(/d)(/d)'', ''123'') (''1'', ''2'', ''3'') >>> groups(r''(/d)(/d)(/d)'', ''abc'') ('''', '''', '''') """ import re m = re.search(regexp, s) if m: return m.groups() return ('''',) * len(m.groups())


def num_groups(regex): return re.compile(regex).groups


f_x = re.search(...) len_groups = len(f_x.groups())