Comment supprimer une nouvelle ligne de fin?


1689

Quel est l'équivalent Python de la chompfonction de Perl , qui supprime le dernier caractère d'une chaîne s'il s'agit d'une nouvelle ligne?


2
Surensemble: n'importe quelle chaîne au lieu d'une simple ligne: stackoverflow.com/questions/1038824/…
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

3
La réponse A + est, si cela était dû à l'oubli d' open()un fichier avec le paramètre 'newline = ...' approprié pour votre plate-forme (prise en charge universelle de la nouvelle ligne), vous pourriez ne pas avoir besoin de le supprimer explicitement.
smci

Réponses:


1868

Essayez la méthode rstrip()(voir doc Python 2 et Python 3 )

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

La rstrip()méthode de Python supprime toutes sortes d'espaces blancs par défaut, pas seulement une nouvelle ligne comme Perl le fait chomp.

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

Pour supprimer uniquement les retours à la ligne:

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

Il y a aussi les méthodes lstrip()et 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
Je ne suis pas une personne Python donc je n'ai pas la réponse à cela, mais chomp () de Perl supprime en fait le séparateur d'enregistrement d'entrée de la fin. C'est une nouvelle ligne sur les choses Unixy, mais peut être différente (par exemple Windows) et elle est modifiable. Existe-t-il un moyen de supprimer cette valeur une seule fois à la fin d'une chaîne?
brian d foy

5
brian d foy: Python n'a pas de séparateur d'enregistrement d'entrée comme awk et Perl.
Peter Hosey

7
@csde_rats, ce n'est pas vrai: OS X utilise \npour les nouvelles lignes comme Unix. (Avant OS X, MacOS utilisait \rcomme séparateur de ligne, mais cela a pris fin il y a 10 ans.)
skue

21
@briandfoy Python a un support intégré pour les nouvelles lignes universelles (uniquement lors de la lecture, pas lors de l'écriture). Vous ouvrez le fichier en mode "U" ou "rU", puis indépendamment de Windows, Linux, Mac, peu importe, au moment où le texte atteint votre code python, tout style de nouvelle ligne a été remplacé par "\ n". Voir: python.org/dev/peps/pep-0278
AlcubierreDrive

12
Je vais aller de l'avant et expliquer cela parce que je suis un noob et j'ai passé un certain temps à me demander pourquoi cela ne fonctionnait pas. .strip()ne modifie pas la chaîne (a probablement quelque chose à voir avec les chaînes immuables). Si ce n'est pas en ligne de commande, vous voudrez"string = string.strip()"
Script Kitty


146

La manière canonique de supprimer les caractères de fin de ligne (EOL) consiste à utiliser la méthode chaîne rstrip () en supprimant tout \ r ou \ n de fin. Voici des exemples de caractères EOL pour Mac, Windows et 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'utilisation de '\ r \ n' comme paramètre pour rstrip signifie qu'il supprimera toute combinaison finale de '\ r' ou '\ n'. C'est pourquoi cela fonctionne dans les trois cas ci-dessus.

Cette nuance est importante dans de rares cas. Par exemple, j'ai dû traiter une fois un fichier texte contenant un message HL7. La norme HL7 requiert un «\ r» de fin comme caractère EOL. La machine Windows sur laquelle j'utilisais ce message avait ajouté son propre caractère EOL '\ r \ n'. Par conséquent, la fin de chaque ligne ressemblait à «\ r \ r \ n». Utiliser rstrip ('\ r \ n') aurait enlevé tout le '\ r \ r \ n' qui n'est pas ce que je voulais. Dans ce cas, j'ai simplement coupé les deux derniers caractères à la place.

Notez que contrairement à la chompfonction de Perl , cela supprimera tous les caractères spécifiés à la fin de la chaîne, pas un seul:

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

7
Notez que les applications Mac OS X modernes utilisent \ n. Seules les anciennes applications Carbon écrites à l'origine pour Mac OS utilisent \ r.
Peter Hosey

2
Merci pour la clarification. Bien sûr, le rstrip ('\ r \ n') fonctionne toujours dans ce cas également.
Mike

13
Il y a aussi os.linesep, qui contient la séquence EOL pour le système d'exploitation actuel.
Eli Collins

C'est la meilleure réponse: il supprime uniquement les nouvelles lignes et le fait correctement pour les plates-formes les plus courantes.
kevinarpe

plus +1 pour utiliser \net\r
fechnert

99

Notez que rstrip n'agit pas exactement comme chomp () de Perl car il ne modifie pas la chaîne. Autrement dit, en Perl:

$x="a\n";

chomp $x

se traduit par l' $xêtre "a".

mais en Python:

x="a\n"

x.rstrip()

signifie que la valeur de xest toujours "a\n" . Même x=x.rstrip()ne donne pas toujours le même résultat, car il supprime tous les espaces à la fin de la chaîne, pas un seul saut de ligne au plus.


7
En outre, strip () supprime les caractères répétés, tandis que chop / chomp ne supprime qu'une seule nouvelle ligne
kostmo

50

Je pourrais utiliser quelque chose comme ça:

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

Je pense que le problème rstrip("\n")est que vous voudrez probablement vous assurer que le séparateur de ligne est portable. (certains systèmes archaïques seraient utilisés "\r\n"). L'autre problème est que rstriples espaces blancs répétés seront supprimés. Espérons os.linesepqu'il contiendra les bons personnages. ce qui précède fonctionne pour moi.


12
Cela ne fonctionnera cependant pas si vous essayez de nettoyer le contenu soumis par l'utilisateur dans une application Web. Le contenu utilisateur peut provenir de n'importe quelle source et contenir des caractères de nouvelle ligne.
apiguy

2
Bon point, sauf que vous pouvez traiter des fichiers «étrangers» (à partir de systèmes désuets) sur votre système d'exploitation moderne.
ChuckCottrill

1
Gardez également à l'esprit que si vous lisez un fichier en mode texte, cela ne fonctionnera pas non plus sur un système Windows, car le caractère de fin sera toujours converti en '\ n'.
Mad Physicist

@MadPhysicist Vous avez raison, il le convertit, mais il fonctionne toujours car il est identique à rstrip('\r\n')et rstrip()supprimera tous les caractères qui se trouvent dans l'argument.
dtauxe

41

Vous pouvez utiliser line = line.rstrip('\n'). Cela supprimera tous les sauts de ligne de la fin de la chaîne, pas un seul.


35
s = s.rstrip()

supprimera toutes les nouvelles lignes à la fin de la chaîne s. L'affectation est nécessaire car rstriprenvoie une nouvelle chaîne au lieu de modifier la chaîne d'origine.


33

Cela reproduirait exactement le chomp de perl (comportement moins sur les tableaux) pour le terminateur de ligne "\ 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

(Remarque: il ne modifie pas la chaîne "en place"; il ne supprime pas les espaces de fin supplémentaires; prend \ r \ n en compte)


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

ou vous pourriez toujours devenir plus geek avec des expressions rationnelles :)

s'amuser!


Cela a très bien fonctionné pour moi en essayant de transformer rapidement un fichier texte avec des fins de ligne en une seule ligne de texte. Je suis un débutant, donc je ne sais pas s'il y a une meilleure façon de le faire, mais cela a fonctionné, merci! (Strip ne semblait fonctionner que des extrémités, pas en interne)
Steve Koch

2
Pourquoi ne pas simplement utiliser une instruction replace, comme .replace('\n|\r', '')?
tckmn

2
Juste au cas où quelqu'un d'autre voudrait utiliser l'idée de @DoorknobofSnow, c'est juste un petit changement pour utiliser le module regex: import re re.sub('\n|\r', '', '\nx\n\r\n')==> 'x'.
Taylor Edmiston

Utiliser cette technique et l'expression régulière comme @TaylorEdmiston devrait être la bonne réponse.
Bhargav

@Bhargav J'ai ajouté une réponse à cette question sur la base de ce commentaire comme vous l'avez suggéré tout en explorant quelques autres options connexes. J'ai également expliqué pourquoi je pense que regex est une meilleure solution à ce problème que str.rstrip puisque c'est ce que la plupart des réponses utilisent.
Taylor Edmiston

27

vous pouvez utiliser la bande:

line = line.strip()

démo:

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

1
J'ai essayé cette solution, mais elle supprime les premiers blancs de la ligne.
Tarik

@Tarik vous pouvez utiliser rstrip
Hackaholic

rstrip supprimera tous les espaces de fin, contrairement à chomp qui ne supprime au plus qu'une nouvelle ligne.
Flimm

20

rstrip ne fait pas la même chose que chomp, sur tant de niveaux. Lisez http://perldoc.perl.org/functions/chomp.html et voyez que chomp est vraiment très complexe.

Cependant, mon point principal est que chomp supprime au plus 1 fin de ligne, tandis que rstrip en supprimera autant que possible.

Ici, vous pouvez voir rstrip supprimer toutes les nouvelles lignes:

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

Une approximation beaucoup plus proche de l'utilisation typique de chomp Perl peut être accomplie avec re.sub, comme ceci:

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

2
Bravo, vous êtes le seul à avoir souligné ce détail très important. Cependant, comme l'a noté quelqu'un ci-dessus, l'utilisation d'os.linesep ne fonctionnera pas si vous lisez des fichiers à partir d'un système différent. Cela pourrait prendre un peu plus de travail en Python, inspectant en fait la fin de la ligne.
brianmearns

19

Attention à "foo".rstrip(os.linesep): cela ne fera que couper les caractères de nouvelle ligne pour la plate-forme sur laquelle votre Python est exécuté. Imaginez que vous trafiquez les lignes d'un fichier Windows sous Linux, par exemple:

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

Utilisez "foo".rstrip("\r\n")plutôt, comme Mike l'a dit ci-dessus.


L'autre chose à noter est qu'il ne supprime pas au plus une nouvelle ligne, mais toutes les nouvelles lignes, contrairement chomp.
Flimm

19

Un exemple dans la documentation de Python utilise simplement line.strip().

La chompfonction de Perl supprime une séquence de saut de ligne de la fin d'une chaîne uniquement si elle est réellement là.

Voici comment je prévois de le faire en Python, si processc'est conceptuellement la fonction dont j'ai besoin pour faire quelque chose d'utile à chaque ligne de ce fichier:

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
Enfin, une réponse qui ne le supprime qu'une seule fois (comme le chomp réel ...) et qui est OS portable!
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

13

Je ne programme pas en Python, mais je suis tombé sur une FAQ sur python.org préconisant S.rstrip ("\ r \ n") pour python 2.2 ou version ultérieure.


10
import re

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

2
Cela va également supprimer les espaces de tabulation, ce que la question d'origine ne demande pas. (En raison du caractère \ t)
NoahR

9

Je trouve pratique d'avoir pu obtenir les lignes hachées via l'itérateur, parallèlement à la façon dont vous pouvez obtenir les lignes non hachées à partir d'un objet fichier. Vous pouvez le faire avec le code suivant:

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

Exemple d'utilisation:

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

Note: Avec operator.methodcalleret map( itertools.imapsur AP2) vous pouvez pousser ce travail à la couche C, en évitant le code de générateur de niveau Python (et en cours d' exécution ainsi un peu plus vite, mais il est vrai E / S est en tête susceptible de masquer les petits gains): for line in map(operator.methodcaller('rstrip', '\r\n'), infile):. Il pourrait encore être factorisé comme def chomped_lines(it): return map(operator.methodcaller('rstrip', '\r\n'), it).
ShadowRanger

8

solution de contournement pour un cas spécial:

si le caractère de nouvelle ligne est le dernier caractère (comme c'est le cas avec la plupart des entrées de fichier), alors pour tout élément de la collection, vous pouvez indexer comme suit:

foobar= foobar[:-1]

pour découper votre caractère de nouvelle ligne.


3
Parfois, la nouvelle ligne n'est pas un dernier caractère, mais les derniers, spécialement sur les fenêtres, comme d'autres l'ont souligné.
Cacovsky

8

Si votre question est de nettoyer tous les sauts de ligne dans un objet chaîne à plusieurs lignes (oldstr), vous pouvez le diviser en une liste en fonction du délimiteur '\ n', puis joindre cette liste en une nouvelle chaîne (newstr).

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


7

Il semble qu'il n'y ait pas d'analogue parfait pour le chomp de Perl . En particulier, rstrip ne peut pas gérer les délimiteurs de nouvelle ligne multi-caractères comme \r\n. Cependant, splitlines fait comme indiqué ici . Suite à ma réponse à une autre question, vous pouvez combiner jointure et splitlines pour supprimer / remplacer tous les retours à la ligne d'une chaîne s:

''.join(s.splitlines())

Ce qui suit supprime exactement une nouvelle ligne de fin (comme le ferait chomp, je crois). Passer Truecomme keependsargument aux lignes de séparation conserve les délimiteurs. Ensuite, splitlines est appelé à nouveau pour supprimer les délimiteurs sur la dernière "ligne" uniquement:

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

7

Je bouillonne ma réponse basée sur l'expression régulière de celle que j'ai publiée plus tôt dans les commentaires d'une autre réponse. Je pense que l'utilisation reest une solution plus claire et explicite à ce problème que str.rstrip.

>>> import re

Si vous souhaitez supprimer un ou plusieurs caractères de fin de ligne:

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

Si vous souhaitez supprimer les caractères de nouvelle ligne partout (pas seulement à la fin):

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

Si vous voulez supprimer seulement 1-2 caractères de nouvelle ligne de fuite (c. -à- \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'

J'ai l'impression que la plupart des gens veulent vraiment ici, c'est supprimer une seule occurrence d'un caractère de fin de ligne, soit \r\nou \net rien de plus.

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

(Le ?: s'agit de créer un groupe non capturant.)

(Soit dit en passant, ce n'est pas ce '...'.rstrip('\n', '').rstrip('\r', '')qui ne peut être clair pour les autres qui tombent sur ce fil. str.rstripSupprime autant de caractères de fin que possible, donc une chaîne comme foo\n\n\ncela entraînerait un faux positif fooalors que vous souhaitiez peut-être conserver le d'autres sauts de ligne après en avoir retiré un.)


Vous pouvez ignorer le groupe non capturant, même pour votre approche finale, avec l'expression régulière r'\r?\n$'. Probablement plus efficace, car les moteurs regex ont plus de mal à optimiser les alternances. Notez également que si vous allez le faire plusieurs fois, cela sera beaucoup plus rapide (surtout si vous vous mélangez à d'autres reutilisations) à re.compilel'expression une fois à l'avant, puis utilisez la subméthode de l'objet regex compilé; les fonctions du module sont au niveau Python et vérifient d'abord un cache pour les expressions rationnelles compilées (création / mise en cache s'il manque), puis appelez la méthode de correspondance; sauter cette recherche aide.
ShadowRanger

1
En outre, note latérale: Puisque vous essayez de faire correspondre \ndirectement le, vous pouvez utiliser \Zover $(ou simplement faire correspondre \r?$, car $peut implicitement correspondre juste avant la nouvelle ligne à la fin d'une chaîne).
ShadowRanger

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

L'exemple dont j'avais besoin! Donc rstrip ("\ r \ n") supprimera à la fois '\ n' et '\ r' dans n'importe quelle combinaison à la fin de la ligne!
Agostino

@Agostino Pas besoin de fournir "\r\n"Par exemple: ' spacious \n\r\n\r \n\n'.rstrip()produit' spacious'
olibre

2
@olibre le code que vous proposez supprimera également les autres caractères vides / espaces, ce qui pourrait ne pas être ce dont on a besoin. En fait, je n'avais besoin que de supprimer les combinaisons de caractères eol. Merci encore de l'avoir signalé.
Agostino

4

Utilisez simplement:

line = line.rstrip("\n")

ou

line = line.strip("\n")

Vous n'avez besoin d'aucune de ces choses compliquées


2
Notez que ce n'est pas la même chose que 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'

Avec regex

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

Remplacer \ n, \ t, \ r

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

Avec regex

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

avec Join

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

3

Il existe trois types de terminaisons de ligne que l' on rencontre normalement: \n, \ret \r\n. Une expression régulière assez simple dans re.sub, à savoir r"\r?\n?$", est capable de tous les attraper.

(Et nous devons tous les attraper , ai-je raison?)

import re

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

Avec le dernier argument, nous limitons le nombre d'occurrences remplacées à un, imitant le chomp dans une certaine mesure. Exemple:

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)

... où a == b == cest True.


Vous n'avez même pas besoin d'expressions régulières à part entière. rstrip("\r\n")est un fourre-tout. Essayez print(text_2.rstrip('\r\n')).
Agostino

@Agostino: Vrai, étant donné que cela str.rstrip()résout le problème. Cela dépend de vos besoins. Cette solution est spécialement conçue pour les cas où vous devez supprimer uniquement le dernier "\n", "\r"ou "\r\n"pas tous (s'il y en a plusieurs "\n"dans la chaîne). re.sub(r"\r?\n?$", "", text_1, 1)renvoie "hellothere\n\n"et text_1.rstrip("\r\n")renvoie "hellothere"une chaîne différente.
internetional

Ce que j'essaie de dire, c'est que str.strip()c'est un fourre-tout qui est parfois le problème même.
internetional

1

Si vous êtes préoccupé par la vitesse (disons que vous avez une longue liste de chaînes) et que vous connaissez la nature du caractère de nouvelle ligne, le découpage des chaînes est en fait plus rapide que rstrip. Un petit test pour illustrer cela:

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

Production:

Method 1: 3.92700004578
Method 2: 6.73000001907

Je sais que je devrais probablement utiliser des "boucles globales" à l'intérieur des fonctions, mais cela fonctionne aussi.
Stephen Miller

Ce test est faux et pas juste. En ce moment, method1vous coupez simplement le dernier caractère, quoi qu'il en soit, lors method2des .rstrip()premières vérifications, si la fin de la chaîne contient des caractères indésirables et les coupe, uniquement si certains ont été trouvés. Veuillez implémenter une vérification des caractères method1et tester agin!
spky

Comme je l'ai dit dans l'introduction de la réponse: si vous connaissez la nature du caractère de nouvelle ligne, cela est utile. Si vous ne le faites pas alors, vous devez évidemment implémenter une sorte de vérification des caractères - ou simplement utiliser rstrip. Je ne voulais pas être "injuste" à rstrip, mais simplement illustrer une différence pas si insignifiante qui peut valoir la peine d'être considérée dans certaines situations.
Stephen Miller,

1

Cela fonctionnera à la fois pour Windows et Linux (peu coûteux avec re sub si vous recherchez uniquement une solution re)

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


3
Pourquoi utiliser re.searchlà où vous avez juste besoin re.sub?
wjandrea

0

Commencez par séparer les lignes par le séparateur de votre choix:

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

devrait fonctionner comme un charme.


-1

Un fourre-tout:

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

5
rstripne prend pas d'expression régulière. "hi|||\n\n".rstrip("\r|\n")retours"hi"
Flimm
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.