¿Por qué importa el orden de las expresiones en re.match?
Estoy creando una función que tomará una cadena como “three()” o algo como “{1 + 2}” y los pondrá en una lista de tokens (por ejemplo, “three()” = [“three”, “(“, “)”]). Estoy utilizando re.match para ayudar a separar la cadena.
def lex(s):
# escanear la cadena de entrada y devolver una lista de tokens
seq = []
patterns = (r"^(\t|\n|\r| )*(([a-z])*|[0-9]|\(|\)|\*|\/|)(\t|\n|\r| )*")
m = re.match(patterns,s)
while m != None:
if s == '':
break
seq.append(m.group(2))
s = s[len(m.group(0)):]
m = re.match(patterns,s)
return seq
Esta función funciona si la cadena es simplemente “three”. Pero si la cadena contiene “()” o cualquier símbolo, se queda dentro del bucle while.
Pero algo curioso sucede cuando se mueve ([a-z])* en la cadena de patrón, entonces funciona. ¿Por qué está sucediendo esto?
funciona: patterns = (r"^(\t|\n|\r| )*([0-9]|\(|\)|\*|\/|([a-z])*)(\t|\n|\r| )*")
No funciona: patterns = (r"^(\t|\n|\r| )*(([a-z])*|[0-9]|\(|\)|\*|\/)(\t|\n|\r| )*")
davy.ai
La razón por la que mover ([a-z])* en la cadena de patrón hace que el código funcione es porque cambia el orden en que se coinciden las expresiones regulares. En la cadena de patrón que no funciona, el ([a-z])* está dentro de un grupo con el símbolo pipe (|), lo que significa que la expresión regular coincidirá con el grupo con ([a-z])* o los caracteres [0-9]|(|)|*|\/. Esto hace que la expresión regular coincida solo con las letras y no con los símbolos, lo que resulta en un bucle infinito cuando hay símbolos presentes.
Por otro lado, en la cadena de patrón que funciona, ([a-z])* está fuera del grupo con el símbolo pipe, lo que significa que la expresión regular coincidirá con letras o símbolos. Cambiar el orden en el que se coinciden las expresiones regulares permite que el código separe correctamente las cadenas con símbolos en una lista de tokens.