Come posso rimuovere una nuova riga finale?


1689

Qual è l'equivalente Python della chompfunzione di Perl , che rimuove l'ultimo carattere di una stringa se è una nuova riga?


2
Superset: qualsiasi stringa invece di ritorno a capo: stackoverflow.com/questions/1038824/...
Ciro Santilli郝海东冠状病六四事件法轮功

3
La risposta A + è, se ciò era dovuto alla dimenticanza di open()un file con il parametro 'newline = ...' appropriato per la tua piattaforma (supporto universale per la nuova linea), potrebbe non essere necessario rimuoverlo esplicitamente.
smci

Risposte:


1868

Prova il metodo rstrip()(vedi doc Python 2 e Python 3 )

>>> 'test string\n'.rstrip()
'test string'

Il rstrip()metodo di Python elimina tutti i tipi di spazio bianco finale per impostazione predefinita, non solo una nuova riga come fa Perl chomp.

>>> 'test string \n \r\n\n\r \n\n'.rstrip()
'test string'

Per eliminare solo le nuove righe:

>>> 'test string \n \r\n\n\r \n\n'.rstrip('\n')
'test string \n \r\n\n\r '

Esistono anche i metodi lstrip()e 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'

22
Non sono una persona Python, quindi non ho la risposta a questo, ma il chomp () di Perl in realtà rimuove il separatore del record di input dalla fine. Questa è una novità sulle cose di Unixy, ma potrebbe essere diversa (ad esempio Windows) ed è mutabile. C'è un modo per rimuovere quel valore solo una volta dalla fine di una stringa?
brian d foy,

5
brian d foy: Python non ha un separatore di record di input come awk e Perl.
Peter Hosey,

7
@csde_rats, non è vero: OS X usa \nper le nuove linee proprio come Unix. (Prima di OS X, MacOS lo utilizzava \rcome separatore di riga, ma è terminato 10 anni fa.)
skue

21
@briandfoy Python ha il supporto integrato per le newline di Universal (solo durante la lettura, non durante la scrittura). Apri il file in modalità "U" o "rU", e quindi indipendentemente da Windows, Linux, Mac, qualunque sia, quando il testo raggiunge il tuo codice Python, qualsiasi stile di newline è stato sostituito con "\ n". Vedi: python.org/dev/peps/pep-0278
Alcubierre

12
Ho intenzione di andare avanti e spiegarlo perché sono un noob e ho passato un po 'a chiedermi perché non funzionasse. .strip()non altera la stringa (probabilmente ha qualcosa a che fare con stringhe immutabili). Se non nella riga di comando, ti consigliamo"string = string.strip()"
Script Kitty,


146

Il modo canonico di eliminare i caratteri di fine riga (EOL) consiste nell'utilizzare il metodo string rstrip () rimuovendo eventuali tracce finali \ r o \ n. Ecco alcuni esempi di caratteri EOL per Mac, Windows e 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'

L'uso di '\ r \ n' come parametro per rstrip significa che eliminerà qualsiasi combinazione finale di '\ r' o '\ n'. Ecco perché funziona in tutti e tre i casi sopra.

Questa sfumatura è importante in rari casi. Ad esempio, una volta ho dovuto elaborare un file di testo che conteneva un messaggio HL7. Lo standard HL7 richiede un '\ r' finale come carattere EOL. La macchina Windows su cui stavo usando questo messaggio aveva aggiunto il proprio carattere EOL '\ r \ n'. Pertanto, la fine di ogni riga sembrava '\ r \ r \ n'. L'uso di rstrip ('\ r \ n') avrebbe tolto l'intero '\ r \ r \ n' che non è quello che volevo. In tal caso, ho semplicemente semplicemente tagliato gli ultimi due caratteri.

Nota che a differenza della chompfunzione di Perl , questo eliminerà tutti i caratteri specificati alla fine della stringa, non solo uno:

>>> "Hello\n\n\n".rstrip("\n")
"Hello"

7
Nota che le moderne app di Mac OS X usano \ n. Solo le vecchie app Carbon scritte originariamente per Mac OS usano \ r.
Peter Hosey,

2
Grazie per il chiarimento. Ovviamente, rstrip ('\ r \ n') funziona anche in quel caso.
Mike,

13
C'è anche os.linesep, che contiene la sequenza EOL per il sistema operativo corrente.
Eli Collins,

Questa è la risposta migliore: rimuove solo le nuove righe e lo fa correttamente per le piattaforme più comuni.
Kevinevpe,

più +1 Per l'utilizzo di \ne\r
fechnert,

99

Nota che rstrip non si comporta esattamente come il chomp () di Perl perché non modifica la stringa. Cioè, in Perl:

$x="a\n";

chomp $x

risulta in $xessere "a".

ma in Python:

x="a\n"

x.rstrip()

significherà che il valore di xè fermo "a\n" . Anche x=x.rstrip()non dà sempre lo stesso risultato, poiché rimuove tutto lo spazio bianco dalla fine della stringa, non solo una nuova riga al massimo.


7
Inoltre, strip () rimuove i caratteri ripetuti, mentre chop / chomp rimuove solo una nuova riga
kostmo

50

Potrei usare qualcosa del genere:

import os
s = s.rstrip(os.linesep)

Penso che il problema rstrip("\n")sia che probabilmente vorrai assicurarti che il separatore di linea sia portatile. (si dice che alcuni sistemi antiquati vengano utilizzati "\r\n"). L'altro gotcha è che eliminerà rstripgli spazi bianchi ripetuti. Spero os.linesepche conterrà i personaggi giusti. quanto sopra funziona per me.


12
Ciò non funzionerà tuttavia se si sta tentando di ripulire il contenuto inviato dall'utente in un'applicazione Web. Il contenuto dell'utente potrebbe provenire da qualsiasi fonte e contenere qualsiasi carattere di nuova riga.
apiguy

2
Un buon punto, tranne per il fatto che potresti elaborare file "estranei" (da sistemi antiquati) sul tuo sistema operativo moderno.
ChuckCottrill,

1
Tieni presente anche che se stai leggendo un file in modalità testo, anche questo non funzionerà su un sistema Windows, poiché il carattere finale verrà sempre convertito in '\ n'.
Fisico pazzo,

@MadPhysicist Hai ragione che lo converte, ma funziona ancora perché è lo stesso di rstrip('\r\n')e rstrip()rimuoverà tutti i caratteri che sono nell'argomento.
Deluxe

41

Puoi usare line = line.rstrip('\n'). Questo eliminerà tutte le nuove righe dalla fine della stringa, non solo una.


35
s = s.rstrip()

rimuoverà tutte le nuove righe alla fine della stringa s. L'assegnazione è necessaria perché rstriprestituisce una nuova stringa invece di modificare la stringa originale.


33

Questo replicherebbe esattamente il chomp di perl (meno il comportamento sugli array) per il terminatore di riga "\ 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: non modifica la stringa "sul posto"; non rimuove gli spazi vuoti finali in eccesso; prende in considerazione \ r \ n)


27
"line 1\nline 2\r\n...".replace('\n', '').replace('\r', '')
>>> 'line 1line 2...'

o potresti sempre diventare più geek con regexps :)

divertiti!


Per me ha funzionato alla grande, cercando di trasformare rapidamente un file di testo con terminazioni di riga in una riga di testo. Sono un principiante, quindi non sono sicuro se c'è un modo migliore per farlo, ma ha funzionato, grazie! (Strip sembrava funzionare solo dalle estremità, non internamente)
Steve Koch,

2
Perché non usare semplicemente un'istruzione di sostituzione, come .replace('\n|\r', '')?
Martedì

2
Nel caso in cui chiunque voglia utilizzare l'idea di @DoorknobofSnow, è solo una piccola modifica per utilizzare il modulo regex: import re re.sub('\n|\r', '', '\nx\n\r\n')==> 'x'.
Taylor Edmiston,

L'uso di questa e della tecnica regex come menzionato da @TaylorEdmiston dovrebbe essere la risposta corretta.
Bhargav,

@Bhargav Ho aggiunto una risposta a questa domanda sulla base di questo commento, come hai suggerito, esplorando anche alcune altre opzioni correlate. Ho anche chiarito perché penso che regex sia una soluzione migliore a questo problema rispetto a str.rstrip poiché è quello che usano la maggior parte delle risposte.
Taylor Edmiston,

27

puoi usare strip:

line = line.strip()

demo:

>>> "\n\n hello world \n\n".strip()
'hello world'

1
Ho provato questa soluzione ma rimuove gli spazi vuoti iniziali nella linea.
Tarik

@Tarik puoi usare rstrip
Hackaholic

rstrip eliminerà tutto lo spazio bianco finale, a differenza di chomp che elimina solo al massimo una nuova riga.
Flimm,

20

rstrip non fa la stessa cosa di chomp, su così tanti livelli. Leggi http://perldoc.perl.org/functions/chomp.html e vedi che chomp è davvero molto complesso.

Tuttavia, il mio punto principale è che chomp rimuove al massimo 1 finale di riga, mentre rstrip ne rimuoverà il maggior numero possibile.

Qui puoi vedere rstrip che rimuove tutte le nuove righe:

>>> 'foo\n\n'.rstrip(os.linesep)
'foo'

Un'approssimazione molto più ravvicinata dell'uso tipico di Chomp Perl può essere realizzata con re.sub, come questo:

>>> re.sub(os.linesep + r'\Z','','foo\n\n')
'foo\n'

2
Complimenti, sei l'unico che ha sottolineato questo dettaglio molto importante. Tuttavia, come notato da qualcuno sopra, l'uso di os.linesep non funzionerà se stai leggendo file da un sistema diverso. Questo potrebbe richiedere un po 'più di lavoro in Python, controllando effettivamente la fine della linea.
brianmearns,

19

Attenzione "foo".rstrip(os.linesep): ciò comporterà solo i caratteri di nuova riga per la piattaforma in cui viene eseguito Python. Immagina di scartare le linee di un file Windows sotto Linux, ad esempio:

$ 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'
>>>

Usa "foo".rstrip("\r\n")invece, come dice Mike sopra.


L'altra cosa da notare è che non rimuove al massimo una nuova riga, ma tutte le nuove righe, a differenza chomp.
Flimm,

19

Un esempio nella documentazione di Python usa semplicemente line.strip().

La chompfunzione di Perl rimuove una sequenza di interruzioni di riga dalla fine di una stringa solo se è effettivamente presente.

Ecco come ho intenzione di farlo in Python, se processconcettualmente è la funzione di cui ho bisogno per fare qualcosa di utile per ogni riga di questo file:

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)

2
Infine, una risposta che la rimuove solo una volta (come l'attuale chomp ...) ed è portatile OS!
Ciro Santilli 26 冠状 病 六四 事件 法轮功 il

13

Non programma in Python, ma ho trovato una FAQ su python.org a sostegno di S.rstrip ("\ r \ n") per Python 2.2 o versioni successive.


10
import re

r_unwanted = re.compile("[\n\t\r]")
r_unwanted.sub("", your_text)

2
Questo rimuoverà anche gli spazi bianchi delle schede, che la domanda originale non richiede. (A causa del carattere \ t)
NoahR

9

Trovo conveniente poter essere in grado di ottenere le linee tratteggiate tramite in iteratore, parallelamente al modo in cui è possibile ottenere le linee non tratteggiate da un oggetto file. Puoi farlo con il seguente codice:

def chomped_lines(it):
    return map(operator.methodcaller('rstrip', '\r\n'), it)

Esempio di utilizzo:

with open("file.txt") as infile:
    for line in chomped_lines(infile):
        process(line)

Nota: Con operator.methodcallere map( itertools.imapsu PY2) si può spingere questo lavoro al livello C, evitando Python codice generatore di livelli (e funzionante in tal modo un po 'più veloce, anche se certamente di I / O è in testa probabilmente per mascherare piccoli guadagni) for line in map(operator.methodcaller('rstrip', '\r\n'), infile):. Potrebbe essere ancora preso in considerazione come def chomped_lines(it): return map(operator.methodcaller('rstrip', '\r\n'), it).
ShadowRanger

8

soluzione alternativa per casi speciali:

se il carattere di nuova riga è l'ultimo carattere (come nel caso della maggior parte degli input di file), quindi per qualsiasi elemento della raccolta è possibile indicizzare come segue:

foobar= foobar[:-1]

per dividere il tuo personaggio newline.


3
A volte la newline non è un ultimo personaggio, ma gli ultimi, specialmente su Windows, come altri hanno sottolineato.
Cacovsky,

8

Se la tua domanda è di ripulire tutte le interruzioni di riga in un oggetto str a più righe (oldstr), puoi dividerlo in un elenco in base al delimitatore '\ n' e quindi unire questo elenco in un nuovo str (newstr).

newstr = "".join(oldstr.split('\n'))


7

Sembra che non ci sia un analogo perfetto per il chomp di Perl . In particolare, rstrip non può gestire delimitatori newline multi-carattere come \r\n. Tuttavia, le linee di divisione fanno come indicato qui . Seguendo la mia risposta su una domanda diversa, è possibile combinare join e linee di divisione per rimuovere / sostituire tutte le nuove righe da una stringa s:

''.join(s.splitlines())

Quanto segue rimuove esattamente una nuova riga finale (come direbbe chomp). Il passaggio Truecome keependsargomento alle linee di divisione mantiene i delimitatori. Quindi, le linee di divisione vengono nuovamente chiamate per rimuovere i delimitatori solo sull'ultima "linea":

def chomp(s):
    if len(s):
        lines = s.splitlines(True)
        last = lines.pop()
        return ''.join(lines + last.splitlines())
    else:
        return ''

7

Sto ribollendo la mia risposta basata sull'espressione regolare da una che ho pubblicato in precedenza nei commenti di un'altra risposta. Penso che l'utilizzo resia una soluzione più chiara a questo problema rispetto a str.rstrip.

>>> import re

Se si desidera rimuovere uno o più caratteri newline finali :

>>> re.sub(r'[\n\r]+$', '', '\nx\r\n')
'\nx'

Se vuoi rimuovere i caratteri newline ovunque (non solo in coda):

>>> re.sub(r'[\n\r]+', '', '\nx\r\n')
'x'

Se si desidera rimuovere solo 1-2 trascinamento caratteri di nuova linea (cioè \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'

Ho la sensazione che ciò che la maggior parte della gente vuole davvero qui, è di rimuovere solo una ricorrenza di un personaggio newline finale, o \r\no \ne niente di più.

>>> 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'

(Il ?: per creare un gruppo non di acquisizione.)

(A proposito, questo non è ciò '...'.rstrip('\n', '').rstrip('\r', '')che potrebbe non essere chiaro agli altri inciampare su questo thread. str.rstripSpoglia il maggior numero possibile di caratteri finali, quindi una stringa simile foo\n\n\ncomporterebbe un falso positivo di foomentre potresti aver voluto preservare il altre nuove righe dopo aver rimosso una singola traccia.)


Potresti saltare il gruppo che non cattura, anche per il tuo approccio finale, con la regex r'\r?\n$'. Probabilmente più efficiente, dal momento che i motori regex hanno tempi più difficili per ottimizzare le alternanze. Nota anche che se lo farai molte volte, sarà significativamente più veloce (specialmente se ti mescoli con altri reusi) re.compileall'espressione una volta in primo piano, quindi usa il submetodo dell'oggetto regex compilato; le funzioni del modulo sono a livello di Python e controllano prima una regex compilata nella cache (creazione / memorizzazione nella cache se mancante), quindi chiama il metodo corrispondente; saltare quella ricerca aiuta.
ShadowRanger

1
Inoltre, nota a margine: dal momento che stai cercando di abbinare \ndirettamente il, potresti voler usare \Zover $(o semplicemente match \r?$, poiché $implicitamente può corrispondere appena prima della nuova riga alla fine di una stringa).
ShadowRanger

5
>>> '   spacious   '.rstrip()
'   spacious'
>>> "AABAA".rstrip("A")
  'AAB'
>>> "ABBA".rstrip("AB") # both AB and BA are stripped
   ''
>>> "ABCABBA".rstrip("AB")
   'ABC'

L'esempio di cui avevo bisogno! Quindi rstrip ("\ r \ n") eliminerà "\ n" e "\ r" in qualsiasi combinazione alla fine della riga!
Agostino,

@Agostino Non è necessario fornire ad "\r\n"esempio: ' spacious \n\r\n\r \n\n'.rstrip()produce' spacious'
olibre

2
@olibre il codice che suggerirai rimuoverà anche altri caratteri vuoti / spaziali, che potrebbero non essere ciò di cui hai bisogno. In effetti, dovevo solo eliminare le combinazioni di personaggi eol. Tuttavia, grazie per averlo sottolineato.
Agostino,

4

Usa solo:

line = line.rstrip("\n")

o

line = line.strip("\n")

Non hai bisogno di nessuna di queste cose complicate


2
Nota che questo non è lo stesso di chomp.
Flimm,

4
s = '''Hello  World \t\n\r\tHi There'''
# import the module string   
import string
# use the method translate to convert 
s.translate({ord(c): None for c in string.whitespace}
>>'HelloWorldHiThere'

Con regex

s = '''  Hello  World 
\t\n\r\tHi '''
print(re.sub(r"\s+", "", s), sep='')  # \s matches all white spaces
>HelloWorldHi

Sostituisci \ n, \ t, \ r

s.replace('\n', '').replace('\t','').replace('\r','')
>'  Hello  World Hi '

Con regex

s = '''Hello  World \t\n\r\tHi There'''
regex = re.compile(r'[\n\r\t]')
regex.sub("", s)
>'Hello  World Hi There'

con Join

s = '''Hello  World \t\n\r\tHi There'''
' '.join(s.split())
>'Hello  World Hi There'

3

Ci sono tre tipi di fine riga che normalmente incontriamo: \n, \re \r\n. Un'espressione regolare piuttosto semplice in re.sub, vale a direr"\r?\n?$" , è in grado di catturarli tutti.

(E dobbiamo prenderli tutti , vero?)

import re

re.sub(r"\r?\n?$", "", the_text, 1)

Con l'ultimo argomento, limitiamo il numero di occorrenze sostituite a una, imitando in qualche misura il chomp. Esempio:

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)

... dove a == b == cè True.


Non hai nemmeno bisogno di espressioni regolari a tutti gli effetti. rstrip("\r\n")è un vero toccasana. Prova print(text_2.rstrip('\r\n')).
Agostino,

@Agostino: vero, dato che str.rstrip()risolve il problema. Dipende da quali bisogni hai. Questa soluzione è specifica per i casi in cui è necessario rimuovere solo l'ultimo "\n", "\r"o "\r\n"non tutti (se ce ne sono più "\n"nella stringa). re.sub(r"\r?\n?$", "", text_1, 1)restituisce "hellothere\n\n"e text_1.rstrip("\r\n")restituisce "hellothere"una stringa diversa.
Internetional,

Quello che sto cercando di dire è: questo str.strip()è un problema a volte è proprio il problema.
Internetional,

1

Se sei preoccupato per la velocità (supponi di avere un elenco di stringhe troppo lungo) e conosci la natura del carattere newline, l'affettatura delle stringhe è effettivamente più veloce di rstrip. Un piccolo test per illustrare questo:

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()

Produzione:

Method 1: 3.92700004578
Method 2: 6.73000001907

So che dovrei probabilmente usare "loop globali" all'interno delle funzioni, ma funziona anche.
Stephen Miller,

Questo test è sbagliato e non è giusto .. In method1si sta solo tagliando l'ultimo carattere, non importa quale, nei method2i .rstrip()primi controlli, se alla fine della stringa contiene caratteri indesiderati e li costolette fuori, solo se alcuni sono stati trovati. Per favore implementa un po 'di controllo per i personaggi method1e prova ancora!
spky

Come ho detto nell'introduzione alla risposta: se conosci la natura del carattere newline, questo è utile. In caso contrario, ovviamente, è necessario implementare una sorta di controllo del personaggio - o semplicemente usare rstrip. Non intendevo essere "ingiusto" da riprovare, ma semplicemente illustrare una differenza non così insignificante che potrebbe valere la pena considerare in alcune situazioni.
Stephen Miller,

1

Funzionerà sia per Windows che per Linux (un po 'caro con re-sub se stai cercando solo una soluzione)

import re 
if re.search("(\\r|)\\n$", line):
    line = re.sub("(\\r|)\\n$", "", line)


3
Perché usare re.searchdove serve re.sub?
wjandrea,

0

Prima dividi le linee quindi uniscile con qualsiasi separatore che ti piace:

x = ' '.join(x.splitlines())

dovrebbe funzionare come un incantesimo.


-1

Una cattura tutto:

line = line.rstrip('\r|\n')

5
rstripnon prende espressione regolare. "hi|||\n\n".rstrip("\r|\n")ritorna"hi"
Flimm il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.