Expresión regular para eliminar saltos de línea.

Soy un completo novato en Python, y estoy atascado con un problema de expresiones regulares. Estoy tratando de eliminar el carácter de salto de línea al final de cada línea en un archivo de texto, pero solo si sigue una letra minúscula, es decir, [az] . Si el final de la línea termina en minúscula, quiero reemplazar el carácter de salto de línea / nueva línea con un espacio.

Esto es lo que tengo hasta ahora:

 import re import sys textout = open("output.txt","w") textblock = open(sys.argv[1]).read() textout.write(re.sub("[az]\z","[az] ", textblock, re.MULTILINE) ) textout.close() 

Tratar

 re.sub(r"(?<=[az])\r?\n"," ", textblock) 

\Z solo coincide al final de la cadena, después del último salto de línea, por lo que definitivamente no es lo que necesitas aquí. \z no es reconocido por el motor de expresiones regulares de Python.

(?<=[az]) es una aserción de mirada positiva que verifica si el carácter antes de la posición actual es un carácter ASCII en minúscula. Solo entonces el motor de expresiones regulares intentará coincidir con un salto de línea.

Además, siempre use cadenas en bruto con expresiones regulares. Facilita el manejo de las barras invertidas.

Solo como una respuesta alternativa, aunque toma más líneas, creo que lo siguiente puede ser más claro ya que la expresión regular es más simple:

 import re import sys with open(sys.argv[1]) as ifp: with open("output.txt", "w") as ofp: for line in ifp: if re.search('[az]$',line): ofp.write(line.rstrip("\n\r")+" ") else: ofp.write(line) 

… y eso evita cargar el archivo completo en una cadena. Si desea usar menos líneas, pero aún así, evite la apariencia positiva, podría hacer lo siguiente:

 import re import sys with open(sys.argv[1]) as ifp: with open("output.txt", "w") as ofp: for line in ifp: ofp.write(re.sub('(?m)([az])[\r\n]+$','\\1 ',line)) 

Las partes de esa expresión regular son:

  • (?m) [activar concordancia multilínea]
  • ([az]) [coincide con un solo carácter en minúscula como el primer grupo]
  • [\r\n]+ [coincide con uno o más retornos de carro o líneas nuevas, para cubrir \n , \r\n y \r ]
  • $ [coincide con el final de la cadena]

… y si esa línea coincide, la letra minúscula y el final de la línea se reemplazan por \\1 , que será la letra minúscula seguida de un espacio.

mi punto era que evitar el uso de una mirada positiva podría hacer que el código sea más legible

DE ACUERDO. Aunque, personalmente, no me parece que sea menos legible. Es cuestión de gustos.

En su EDIT:

  • Primero, (? M) no es necesario ya que para la línea en ifp: selecciona una línea a la vez, por lo que solo hay una nueva línea al final de la cadena de cada línea

  • En segundo lugar, $ como se coloca, no tiene utilidad porque siempre coincidirá con el final de la línea de cadena.

De cualquier manera, adoptando su punto de vista, encontré dos maneras de evitar la aseveración de la mirada detrás de:

 with open(sys.argv[1]) as ifp: with open("output.txt", "w") as ofp: for line in ifp: ante_newline,lower_last = re.match('(.*?([az])?$)',line).groups() ofp.write(ante_newline+' ' if lower_last else line) 

y

 with open(sys.argv[1]) as ifp: with open("output.txt", "w") as ofp: for line in ifp: ofp.write(line.strip('\r\n')+' ' if re.search('[az]$',line) else line) 

el segundo es mejor: solo una línea, una simple coincidencia a prueba, sin necesidad de grupos (), lógicamente lógica

EDIT: oh, me doy cuenta de que este segundo código es simplemente su primer código reescrito en una línea, Longair