saltos - python separar string por caracter
¿Cómo puedo eliminar(chompar) una nueva línea final en Python? (26)
Cuidado con "foo".rstrip(os.linesep)
: Eso solo afectará a los caracteres de nueva línea de la plataforma donde se está ejecutando Python. Imagina que estás chimping las líneas de un archivo de Windows en Linux, por ejemplo:
$ python
Python 2.7.1 (r271:86832, Mar 18 2011, 09:09:48)
[GCC 4.5.0 20100604 [gcc-4_5-branch revision 160292]] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, sys
>>> sys.platform
''linux2''
>>> "foo/r/n".rstrip(os.linesep)
''foo/r''
>>>
Utilice "foo".rstrip("/r/n")
lugar, como Mike dice arriba.
¿Cuál es el equivalente de Python de la función chomp
de Perl, que elimina el último carácter de una cadena si es una nueva línea?
Esto funcionará tanto para Windows como para Linux (un poco caro con re sub si solo está buscando re)
import re
if re.search("(//r|)//n$", line):
line = re.sub("(//r|)//n$", "", line)
Esto replicaría exactamente el chomp de perl (comportamiento negativo en los arreglos) para el terminador de línea "/ n":
def chomp(x):
if x.endswith("/r/n"): return x[:-2]
if x.endswith("/n") or x.endswith("/r"): return x[:-1]
return x
(Nota: no modifica la cadena ''en su lugar''; no elimina los espacios en blanco finales; toma / r / n en la cuenta)
Estoy burbujeando mi respuesta basada en expresiones regulares de una que publiqué anteriormente en los comentarios de otra respuesta. Creo que usar re
es una solución más clara y explícita a este problema que str.rstrip
.
>>> import re
Si desea eliminar uno o más caracteres de nueva línea finales :
>>> re.sub(r''[/n/r]+$'', '''', ''/nx/r/n'')
''/nx''
Si desea eliminar caracteres de nueva línea en todas partes (no solo en el final):
>>> re.sub(r''[/n/r]+'', '''', ''/nx/r/n'')
''x''
Si desea eliminar solo 1-2 caracteres de nueva línea finales (es decir, /r
, /n
, /r/n
, /n/r
, /r/r
, /n/n
)
>>> re.sub(r''[/n/r]{1,2}$'', '''', ''/nx/r/n/r/n'')
''/nx/r''
>>> re.sub(r''[/n/r]{1,2}$'', '''', ''/nx/r/n/r'')
''/nx/r''
>>> re.sub(r''[/n/r]{1,2}$'', '''', ''/nx/r/n'')
''/nx''
Tengo la sensación de que lo que la mayoría de la gente realmente quiere aquí es eliminar solo una aparición de un carácter de nueva línea final, ya sea /r/n
o /n
nada más.
>>> re.sub(r''(?:/r/n|/n)$'', '''', ''/nx/n/n'', count=1)
''/nx/n''
>>> re.sub(r''(?:/r/n|/n)$'', '''', ''/nx/r/n/r/n'', count=1)
''/nx/r/n''
>>> re.sub(r''(?:/r/n|/n)$'', '''', ''/nx/r/n'', count=1)
''/nx''
>>> re.sub(r''(?:/r/n|/n)$'', '''', ''/nx/n'', count=1)
''/nx''
(El ?:
Es para crear un grupo que no captura).
(Por cierto, esto no es lo que ''...''.rstrip(''/n'', '''').rstrip(''/r'', '''')
hace que no esté claro para otros que se topan con este hilo. str.rstrip
mayor cantidad posible de caracteres finales, por lo que una cadena como foo/n/n/n
resultaría en un falso positivo de foo
mientras que es posible que desee conservar las otras nuevas líneas después de eliminar uno solo.)
Hay tres tipos de finales de línea que normalmente encontramos: /n
, /r
y /r/n
. Una expresión regular bastante simple en re.sub
, a saber r"/r?/n?$"
, Es capaz de capturarlos a todos.
(Y tenemos que atraparlos a todos , ¿tengo razón?)
import re
re.sub(r"/r?/n?$", "", the_text, 1)
Con el último argumento, limitamos el número de ocurrencias reemplazadas a una, imitando chomp hasta cierto punto. Ejemplo:
import re
text_1 = "hellothere/n/n/n"
text_2 = "hellothere/n/n/r"
text_3 = "hellothere/n/n/r/n"
a = re.sub(r"/r?/n?$", "", text_1, 1)
b = re.sub(r"/r?/n?$", "", text_2, 1)
c = re.sub(r"/r?/n?$", "", text_3, 1)
... donde a == b == c
es True
.
La forma canónica de eliminar los caracteres de final de línea (EOL) es usar el método de cadena rstrip () para eliminar cualquier / r o / n. Aquí hay ejemplos de caracteres EOL para Mac, Windows y Unix.
>>> ''Mac EOL/r''.rstrip(''/r/n'')
''Mac EOL''
>>> ''Windows EOL/r/n''.rstrip(''/r/n'')
''Windows EOL''
>>> ''Unix EOL/n''.rstrip(''/r/n'')
''Unix EOL''
Usar ''/ r / n'' como el parámetro a rstrip significa que eliminará cualquier combinación final de ''/ r'' o ''/ n''. Es por eso que funciona en los tres casos anteriores.
Este matiz importa en casos raros. Por ejemplo, una vez tuve que procesar un archivo de texto que contenía un mensaje HL7. El estándar HL7 requiere un ''/ r'' al final como su carácter EOL. La máquina de Windows en la que estaba usando este mensaje había añadido su propio carácter ''/ r / n'' EOL. Por lo tanto, el final de cada línea parecía ''/ r / r / n''. El uso de rstrip (''/ r / n'') habría eliminado todo el ''/ r / r / n'', que no es lo que quería. En ese caso, simplemente corté los dos últimos caracteres en su lugar.
Tenga en cuenta que a diferencia de la función chomp
de Perl, esto eliminará todos los caracteres especificados al final de la cadena, no solo uno:
>>> "Hello/n/n/n".rstrip("/n")
"Hello"
Me parece conveniente poder obtener las líneas segmentadas a través del iterador, paralelamente a la forma en que puede obtener las líneas no segmentadas de un objeto de archivo. Puedes hacerlo con el siguiente código:
def chomped_lines(it):
return map(operator.methodcaller(''rstrip'', ''/r/n''), it)
Uso de la muestra:
with open("file.txt") as infile:
for line in chomped_lines(infile):
process(line)
No programo en Python, pero encontré una FAQ en python.org que promueve S.rstrip ("/ r / n") para python 2.2 o posterior.
Parece que no hay un análogo perfecto para chomp de Perl. En particular, rstrip no puede manejar delimitadores de nueva línea de varios caracteres como /r/n
. Sin embargo, splitlines hace como se indica aquí . Siguiendo mi respuesta en una pregunta diferente, puede combinar las líneas de join y división para eliminar / reemplazar todas las líneas nuevas de una cadena s
:
''''.join(s.splitlines())
Lo siguiente elimina exactamente una nueva línea final (como lo haría chomp, creo). Pasando True
como el argumento de keepends a splitlines retiene los delimitadores. Luego, se vuelve a llamar a splitlines para eliminar los delimitadores solo en la última "línea":
def chomp(s):
if len(s):
lines = s.splitlines(True)
last = lines.pop()
return ''''.join(lines + last.splitlines())
else:
return ''''
Podría usar algo como esto:
import os
s = s.rstrip(os.linesep)
Creo que el problema con rstrip("/n")
es que probablemente querrá asegurarse de que el separador de línea sea portátil. (Se rumorea que algunos sistemas anticuados usan "/r/n"
). El otro problema es que rstrip
eliminará los espacios en blanco repetidos. Esperemos que os.linesep
contenga los caracteres correctos. Lo anterior funciona para mí.
Pruebe el método rstrip()
(consulte el documento Python 2 y Python 3 )
>>> ''test string/n''.rstrip()
''test string''
El método rstrip()
Python rstrip()
todo tipo de espacios en blanco al final de manera predeterminada, no solo una nueva línea como Perl lo hace con chomp
.
>>> ''test string /n /r/n/n/r /n/n''.rstrip()
''test string''
Para desnudar solo nuevas líneas:
>>> ''test string /n /r/n/n/r /n/n''.rstrip(''/n'')
''test string /n /r/n/n/r ''
También están los métodos lstrip()
y strip()
:
>>> s = " /n/r/n /n abc def /n/r/n /n "
>>> s.strip()
''abc def''
>>> s.lstrip()
''abc def /n/r/n /n ''
>>> s.rstrip()
'' /n/r/n /n abc def''
Puede usar line = line.rstrip(''/n'')
. Esto eliminará todas las líneas nuevas del final de la cadena, no solo una.
Si le preocupa la velocidad (digamos que tiene una larga lista de cuerdas) y sabe la naturaleza de la nueva línea de caracteres, el corte de la cuerda es más rápido que rstrip. Una pequeña prueba para ilustrar esto:
import time
loops = 50000000
def method1(loops=loops):
test_string = ''num/n''
t0 = time.time()
for num in xrange(loops):
out_sting = test_string[:-1]
t1 = time.time()
print(''Method 1: '' + str(t1 - t0))
def method2(loops=loops):
test_string = ''num/n''
t0 = time.time()
for num in xrange(loops):
out_sting = test_string.rstrip()
t1 = time.time()
print(''Method 2: '' + str(t1 - t0))
method1()
method2()
Salida:
Method 1: 3.92700004578
Method 2: 6.73000001907
Si su pregunta es limpiar todos los saltos de línea en un objeto str de líneas múltiples (oldstr), puede dividirlo en una lista de acuerdo con el delimitador ''/ n'' y luego unirla a una nueva str (newstr).
newstr = "".join(oldstr.split(''/n''))
Solo usa :
line = line.rstrip("/n")
o
line = line.strip("/n")
No necesitas nada de esto complicado
Solución alternativa para casos especiales:
Si el carácter de nueva línea es el último carácter (como es el caso con la mayoría de las entradas de archivos), entonces para cualquier elemento de la colección puede indexar lo siguiente:
foobar= foobar[:-1]
para cortar su personaje de nueva línea.
Tenga en cuenta que rstrip no actúa exactamente como el chomp () de Perl porque no modifica la cadena. Es decir, en Perl:
$x="a/n";
chomp $x
resulta en $x
siendo "a"
.
pero en Python:
x="a/n"
x.rstrip()
significará que el valor de x
sigue siendo "a/n"
. Incluso x=x.rstrip()
no siempre da el mismo resultado, ya que elimina todos los espacios en blanco del final de la cadena, no solo una nueva línea como máximo.
Un ejemplo en la documentación de Python simplemente usa line.strip()
.
La función chomp
de Perl elimina una secuencia de salto de línea del final de una cadena solo si está realmente allí.
Aquí es cómo planeo hacer eso en Python, si el process
es conceptualmente la función que necesito para hacer algo útil para cada línea de este archivo:
import os
sep_pos = -len(os.linesep)
with open("file.txt") as f:
for line in f:
if line[sep_pos:] == os.linesep:
line = line[:sep_pos]
process(line)
Una captura de todos:
line = line.rstrip(''/r|/n'')
Y diría que la forma "pythonic" de obtener líneas sin caracteres de nueva línea final es splitlines ().
>>> text = "line 1/nline 2/r/nline 3/nline 4"
>>> text.splitlines()
[''line 1'', ''line 2'', ''line 3'', ''line 4'']
puedes usar tira
line = line.strip()
manifestación:
>>> "/n/n hello world /n/n".strip()
''hello world''
rstrip no hace lo mismo que chomp, en muchos niveles. Lea chomp y vea que chomp es realmente muy complejo.
Sin embargo, mi punto principal es que chomp elimina como máximo 1 línea, mientras que rstrip eliminará tantas como pueda.
Aquí puedes ver rstrip eliminando todas las nuevas líneas:
>>> ''foo/n/n''.rstrip(os.linesep)
''foo''
Una aproximación mucho más cercana del uso típico de Perl chomp se puede lograr con re.sub, como esto:
>>> re.sub(os.linesep + r''/Z'','''',''foo/n/n'')
''foo/n''
"line 1/nline 2/r/n...".replace(''/n'', '''').replace(''/r'', '''')
>>> ''line 1line 2...''
o siempre podrías ponerte geekier con expresiones regulares :)
¡que te diviertas!
>>> '' spacious ''.rstrip()
'' spacious''
>>> "AABAA".rstrip("A")
''AAB''
>>> "ABBA".rstrip("AB") # both AB and BA are stripped
''''
>>> "ABCABBA".rstrip("AB")
''ABC''
import re
r_unwanted = re.compile("[/n/t/r]")
r_unwanted.sub("", your_text)
s = s.rstrip()
eliminará todas las líneas nuevas al final de la cadena s
. La asignación es necesaria porque rstrip
devuelve una nueva cadena en lugar de modificar la cadena original.