Quel est l'équivalent Python de la fonction chomp
de Perl, qui supprime le dernier caractère d'une chaîne s'il s'agit d'une nouvelle ligne?
Essayez la méthode rstrip()
(voir doc Python 2 et Python 3 )
>>> 'test string\n'.rstrip()
'test string'
La méthode rstrip()
de Python supprime tous les types d'espaces de fin, par défaut, et non une nouvelle ligne comme le fait Perl avec chomp
.
>>> 'test string \n \r\n\n\r \n\n'.rstrip()
'test string'
Pour ne supprimer que les nouvelles lignes:
>>> 'test string \n \r\n\n\r \n\n'.rstrip('\n')
'test string \n \r\n\n\r '
Il existe 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'
Et je dirais que la méthode "pythonique" pour obtenir des lignes sans les caractères de fin de ligne est le splitlines ().
>>> text = "line 1\nline 2\r\nline 3\nline 4"
>>> text.splitlines()
['line 1', 'line 2', 'line 3', 'line 4']
La méthode la plus efficace pour supprimer les caractères de fin de ligne consiste à utiliser la méthode string rstrip () en supprimant tout\r ou\n final. 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'
Utiliser '\ r\n' comme paramètre à rstrip signifie que cela supprimera toute combinaison finale de '\ r' ou '\ n'. C'est pourquoi cela fonctionne dans les trois cas ci-dessus.
Cette nuance compte dans de rares cas. Par exemple, une fois, j'ai dû traiter un fichier texte contenant un message HL7. La norme HL7 requiert un "\ r" final comme caractère EOL. La machine Windows sur laquelle j’utilisais ce message avait ajouté son propre caractère '\ r\n' EOL. 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 fonction chomp
de Perl, tous les caractères spécifiés à la fin de la chaîne seront supprimés, pas un seul:
>>> "Hello\n\n\n".rstrip("\n")
"Hello"
Notez que rstrip n'agit pas exactement comme la méthode chomp () de Perl car il ne modifie pas la chaîne. C'est-à-dire en Perl:
$x="a\n";
chomp $x
résulte en $x
étant "a"
.
mais en Python:
x="a\n"
x.rstrip()
signifiera que la valeur de x
est still "a\n"
. Même x=x.rstrip()
ne donne pas toujours le même résultat, car il supprime tous les espaces blancs de la fin de la chaîne, pas seulement une nouvelle ligne.
Je pourrais utiliser quelque chose comme ça:
import os
s = s.rstrip(os.linesep)
Je pense que le problème avec rstrip("\n")
est que vous voudrez probablement vous assurer que le séparateur de lignes est portable. (certains systèmes obsolètes sont supposés utiliser "\r\n"
). L’autre acquis est que rstrip
supprimera les espaces répétés. Espérons que os.linesep
contiendra les bons caractères. ce qui précède fonctionne pour moi.
Vous pouvez utiliser line = line.rstrip('\n')
. Cela supprimera toutes les nouvelles lignes de la fin de la chaîne, pas une seule.
s = s.rstrip()
enlèvera toutes les nouvelles lignes à la fin de la chaîne s
. L'affectation est nécessaire car rstrip
renvoie une nouvelle chaîne au lieu de modifier la chaîne d'origine.
"line 1\nline 2\r\n...".replace('\n', '').replace('\r', '')
>>> 'line 1line 2...'
ou vous pouvez toujours devenir geekier avec les expressions rationnelles :)
s'amuser!
Cela répliquerait 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 'in place'; il ne supprime pas les espaces finaux supplémentaires; prend en compte\r\n)
vous pouvez utiliser strip:
line = line.strip()
démo:
>>> "\n\n hello world \n\n".strip()
'hello world'
Attention avec "foo".rstrip(os.linesep)
: Cela ne modifiera que les caractères de nouvelle ligne de la plate-forme sur laquelle votre Python est exécuté. Imaginez que vous modifiez 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 plutôt "foo".rstrip("\r\n")
, comme le dit Mike ci-dessus.
Un exemple dans la documentation de Python utilise simplement line.strip()
.
La fonction chomp
de Perl supprime une séquence de saut de ligne de la fin d'une chaîne uniquement si elle est réellement présente.
Voici comment je compte le faire en Python, si process
est conceptuellement la fonction dont j'ai besoin pour faire quelque chose d’utile pour 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)
rstrip ne fait pas la même chose que chomp, à tant de niveaux. Lire http://perldoc.Perl.org/functions/chomp.html et voir que chomp est vraiment très complexe.
Cependant, mon point principal est que chomp supprime au plus une fin de ligne, alors que rstrip en supprimera autant que possible.
Ici vous pouvez voir que rstrip supprime toutes les nouvelles lignes:
>>> 'foo\n\n'.rstrip(os.linesep)
'foo'
Avec re.sub, vous pouvez obtenir une approximation beaucoup plus précise de l’utilisation type de Perl Chomp:
>>> re.sub(os.linesep + r'\Z','','foo\n\n')
'foo\n'
Je ne programme pas en Python, mais je suis tombé sur un FAQ at python.org préconisant S.rstrip ("\ r\n") pour Python 2.2 ou version ultérieure.
import re
r_unwanted = re.compile("[\n\t\r]")
r_unwanted.sub("", your_text)
Si votre question est de nettoyer tous les sauts de ligne dans un objet str de plusieurs lignes (oldstr), vous pouvez le scinder en une liste en fonction du délimiteur '\ n', puis rejoindre cette liste dans une nouvelle str (newstr).
newstr = "".join(oldstr.split('\n'))
solution de contournement pour cas particulier:
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), vous pouvez alors indexer tout élément de la collection comme suit:
foobar= foobar[:-1]
pour trancher votre personnage newline.
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 à plusieurs caractères tels que \r\n
. Cependant, lignes fractionnées fait comme indiqué ici . Après ma réponse sur une question différente, vous pouvez combiner joindre et splitlines pour supprimer/remplacer toutes les nouvelles lignes d'une chaîne s
:
''.join(s.splitlines())
Ce qui suit supprime exactement une nouvelle ligne trailing (comme le ferait chomp, je crois). Si vous passez True
en tant qu'argument keepends
pour scinder les lignes, les délimiteurs sont conservés. Ensuite, splitlines est appelée à nouveau pour supprimer les délimiteurs uniquement sur la dernière "ligne":
def chomp(s):
if len(s):
lines = s.splitlines(True)
last = lines.pop()
return ''.join(lines + last.splitlines())
else:
return ''
Je trouve pratique de pouvoir obtenir les lignes chompées via l'itérateur, parallèlement à la manière dont vous pouvez obtenir les lignes non chompées d'un objet File 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)
Je bouillonne ma réponse basée sur l'expression régulière d'une réponse que j'ai postée plus tôt dans les commentaires d'une autre réponse. Je pense que l'utilisation de re
est une solution plus claire et plus explicite à ce problème que str.rstrip
.
>>> import re
Si vous souhaitez supprimer un ou plusieurs caractères trailing newline:
>>> 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 souhaitez supprimer uniquement les 1 ou 2 caractères de fin de ligne (c.-à-d., \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 le sentiment que ce que la plupart des gens veulent vraiment ici, est de ne supprimer que un l'occurrence d'un caractère de fin de ligne, soit \r\n
ou \n
et 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 ?:
permet de créer un groupe sans capture.)
(Au fait, c'est pas ce que '...'.rstrip('\n', '').rstrip('\r', '')
fait, ce qui peut ne pas être clair pour les autres qui tombent sur ce fil. str.rstrip
supprime autant de caractères de fin que possible, donc une chaîne comme foo\n\n\n
donnerait un faux positif de foo
alors que vous avez peut-être voulu conserver les autres nouvelles lignes après en avoir effacé une seule.
>>> ' spacious '.rstrip()
' spacious'
>>> "AABAA".rstrip("A")
'AAB'
>>> "ABBA".rstrip("AB") # both AB and BA are stripped
''
>>> "ABCABBA".rstrip("AB")
'ABC'
Il suffit d'utiliser:
line = line.rstrip("\n")
ou
line = line.strip("\n")
Vous n'avez besoin d'aucun de ces trucs compliqués
Nous rencontrons normalement trois types de fins de ligne: \n
, \r
et \r\n
. Une expression régulière assez simple dans re.sub
, à savoir r"\r?\n?$"
, est capable de toutes les attraper.
(Et nous je dois les attraper tous, 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 dans une certaine mesure chomp. 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 == c
est True
.
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 de chaîne est en réalité plus rapide que rstrip. Un petit test pour illustrer ceci:
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()
Sortie:
Method 1: 3.92700004578
Method 2: 6.73000001907
Cela fonctionnera à la fois pour Windows et Linux (un peu cher avec re sous si vous cherchez seulement une solution)
import re
if re.search("(\\r|)\\n$", line):
line = re.sub("(\\r|)\\n$", "", line)