如何删除尾随换行符?


1686

Python与Perl chomp函数等效吗?如果是换行符,它将删除字符串的最后一个字符?



3
A +的答案是,如果这是由于忘记open()了平台上带有适当'newline = ...'参数的文件(通用换行支持),则可能不需要显式删除它。
smci

Answers:


1867

试用该方法rstrip()(请参阅doc Python 2Python 3

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

Python的rstrip()方法去除所有的默认类型的尾随空白的,如Perl并与不只是一个换行符chomp

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

要只删除换行符:

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

还有一些方法lstrip()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
我不是Python人士,所以我没有答案,但是Perl的chomp()实际上从最后删除了输入记录分隔符。这是关于Unixy事物的换行符,但是可能有所不同(例如Windows),并且是可变的。有没有办法从字符串末尾仅删除一次该值?
brian d foy

5
brian d foy:Python没有像awk和Perl那样的输入记录分隔符。
Peter Hosey

7
@csde_rats,事实并非如此:OS X \n与Unix一样用于换行符。(在OS X之前,MacOS确实\r用作行分隔符,但已于10年前终止。)
skue 2012年

21
@briandfoy Python内置了对通用换行符的支持(仅在读取时,而不是在编写时)。您可以以“ U”或“ rU”模式打开文件,然后无论Windows,Linux,Mac(无论如何),在文本到达python代码时,所有换行符样式都将替换为“ \ n”。请参阅:python.org/dev/peps/pep-0278
AlcubierreDrive

11
我要继续进行拼写,因为我是菜鸟,而且花了一段时间想知道为什么它不起作用。.strip()不会更改字符串(可能与不可变的字符串有关)。如果不在命令行中,则需要"string = string.strip()"
Script Kitty


146

删除行尾(EOL)字符的规范方法是使用字符串rstrip()方法,删除任何尾随的\ r或\ n。以下是Mac,Windows和Unix EOL字符的示例。

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

使用'\ r \ n'作为rstrip的参数意味着它会去除'\ r'或'\ n'的任何尾随组合。这就是为什么它在以上所有三种情况下都有效的原因。

这种细微差别在极少数情况下很重要。例如,我曾经不得不处理一个包含HL7消息的文本文件。HL7标准要求结尾的'\ r'作为其EOL字符。我在其上使用此消息的Windows计算机附加了自己的'\ r \ n'EOL字符。因此,每行的末尾看起来像'\ r \ r \ n'。使用rstrip('\ r \ n')会删除整个'\ r \ r \ n',这不是我想要的。在那种情况下,我只是切掉了最后两个字符。

请注意,与Perl的chomp函数不同,这将在字符串的末尾去除所有指定的字符,而不仅仅是一个:

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

7
请注意,现代Mac OS X应用程序使用\ n。仅最初为Mac OS编写的旧版Carbon应用程序使用\ r。
Peter Hosey,

2
感谢您的澄清。当然,在这种情况下,rstrip('\ r \ n')仍然有效。
迈克,

13
还有os.linesep,其中包含当前操作系统的EOL序列。
伊莱·柯林斯

这是最好的答案:它去除换行符,并且在最常见的平台上正确执行。
kevinarpe 2015年

加+1用于使用\n\r
fechnert,2015年

99

请注意,rstrip的行为与Perl的chomp()并不完全相同,因为它不会修改字符串。也就是说,在Perl中:

$x="a\n";

chomp $x

导致$x存在"a"

但在Python中:

x="a\n"

x.rstrip()

将意味着价值x依旧 "a\n"。甚至x=x.rstrip()并不总是给出相同的结果,因为它从字符串的末尾去除所有空格,最多不只是一个换行符。


7
同样,strip()删除重复的字符,而chop / chomp仅删除一个换行符
kostmo 2010年

50

我可能会使用这样的东西:

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

我认为问题rstrip("\n")在于您可能需要确保行分隔符是可移植的。(有传闻说有些过时的系统要使用"\r\n")。另一个难题是,rstrip它将去除重复的空白。希望os.linesep将包含正确的字符。以上对我有用。


12
但是,如果您尝试清除Web应用程序中用户提交的内容,则此方法将无效。用户内容可以来自任何来源,并且可以包含任何换行符。
apiguy 2012年

2
好点,除了您可能正在现代操作系统上处理“过时”文件(来自过时的系统)。
ChuckCottrill'2

1
还请记住,如果您正在以文本模式读取文件,那么这在Windows系统上也将不起作用,因为结尾字符将始终转换为'\ n'。
疯狂物理学家

@MadPhysicist没错,它确实可以转换它,但是它仍然可以工作,因为它与参数相同,rstrip('\r\n')并且rstrip()会删除参数中的所有字符。
dtauxe

41

您可以使用line = line.rstrip('\n')。这将从字符串末尾除去所有换行符,而不仅仅是一条。


35
s = s.rstrip()

将删除字符串末尾的所有换行符s。需要分配是因为rstrip返回一个新字符串而不是修改原始字符串。


33

这将为“ \ n”行终止符精确复制perl的champ(数组的负行为):

def chomp(x):
    if x.endswith("\r\n"): return x[:-2]
    if x.endswith("\n") or x.endswith("\r"): return x[:-1]
    return x

(注意:它不会修改字符串“就地”;它不会去除多余的尾随空格;需要考虑\ r \ n)


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

否则您总是可以通过regexp变得更加怪异:)

玩得开心!


这对于尝试快速将带有行尾的文本文件转换为一行文本非常有用。我是新手,所以不确定是否有更好的方法可以这样做,但是确实有效,谢谢!(条带似乎只能从两端开始工作,而不是从内部开始工作)
Steve Koch

2
为什么不只使用一个replace语句,例如.replace('\n|\r', '')
Doorknob

2
以防万一其他人想要使用@DoorknobofSnow中的想法,使用regex模块只是一个很小的更改:import re re.sub('\n|\r', '', '\nx\n\r\n')==> 'x'
泰勒·埃德米斯顿

使用此和正则表达式技术(如@TaylorEdmiston所述)应该是正确的答案。
巴尔加夫

@Bhargav我根据您的建议在此评论的基础上添加了对此问题的答案,同时还探索了其他一些相关选项。我还阐明了为什么我认为正则表达式比str.rstrip更好的解决此问题的方法,因为这是大多数答案使用的方法。
泰勒·埃德米斯顿

27

您可以使用地带:

line = line.strip()

演示:

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

1
尝试了此解决方案,但它消除了生产线中的主要空白。
塔里克

@Tarik您可以使用rstrip
Hackaholic

rstrip会删除所有结尾的空格,而chomp最多只能删除一个换行符。
Flimm

20

rstrip在很多级别上都没有与chomp相同的功能。阅读http://perldoc.perl.org/functions/chomp.html,发现chomp确实非常复杂。

但是,我的主要观点是chomp最多删除1个行尾,而rstrip会删除尽可能多的行。

在这里,您可以看到rstrip删除了所有换行符:

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

可以使用re.sub来更接近典型的Perl chomp用法,如下所示:

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

2
荣誉,您是唯一指出这一重要细节的人。但是,如上所述,如果您正在从其他系统读取文件,则无法使用os.linesep。在Python中,这可能需要更多的工作,实际上是在检查行尾。
brianmearns 2012年

19

注意"foo".rstrip(os.linesep):只会砍断正在执行Python的平台的换行符。想象一下,例如,您正在用Linux整理Windows文件的行,例如:

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

"foo".rstrip("\r\n")如Mike所说,请改用。


要注意的另一件事是,它最多不会删除一个换行符,而是会删除所有换行符chomp
Flimm

19

Python文档中示例仅使用line.strip()

Perl的chomp函数仅在字符串末尾才删除一个换行序列。

如果process从概念上来说,这是我需要执行的功能,以便对该文件的每一行都有用,这就是我打算在Python 中执行的操作:

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
最后,一个答案只能将其删除一次(例如实际的chomp ...),并且可以移植到操作系统中!
Ciro Santilli冠状病毒审查六四事件法轮功


10
import re

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

2
这也将删除原始问题不要求的制表符空白。(由于\ t字符)
NoahR 2014年

9

我发现能够通过迭代器获得短线很方便,这与从文件对象中获得短线的方式相似。您可以使用以下代码进行操作:

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

用法示例:

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

注意:对于operator.methodcallermapitertools.imap上的Py2),你可以把这个工作交给C层,避免了使用Python水平生成器代码(从而运行快一点,但无可否认的I / O开销可能掩盖小的收益)for line in map(operator.methodcaller('rstrip', '\r\n'), infile):。仍然可以将其排除在外def chomped_lines(it): return map(operator.methodcaller('rstrip', '\r\n'), it)
ShadowRanger

8

特殊情况的解决方法:

如果换行符是最后一个字符(大多数文件输入都是这种情况),那么对于集合中的任何元素,您都可以按如下所示进行索引:

foobar= foobar[:-1]

切出换行符。


3
有时候换行不是一个最后一个字符,但最后的,特别是在Windows上,正如其他人指出。
Cacovsky 2012年

8

如果您的问题是清理多行str对象(oldstr)中的所有换行符,则可以根据定界符'\ n'将其拆分为一个列表,然后将该列表加入一个新的str(newstr)中。

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


7

它看起来像没有用于Perl的一个完美的模拟格格。尤其是,rstrip无法处理多字符换行符分隔符,例如\r\n。但是,分割线确实如此处指出。按照对另一个问题的回答,您可以结合使用joinsplitlines来删除/替换字符串中的所有换行符s

''.join(s.splitlines())

以下内容仅删除了一条尾随的换行符(我相信像排行一样)。Truekeepends参数作为分割线传递时保留定界符。然后,再次调用splitlines以删除最后一个“行”上的分隔符:

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

7

我正在从先前在其他答案的评论中发布的答案中冒充基于正则表达式的答案。我认为使用re可以解决此问题str.rstrip

>>> import re

如果要删除一个或多个尾随换行符,请执行以下操作:

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

如果要在各处删除换行符(不只是尾随):

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

如果你想删除只有1-2尾随换行字符(即\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'

我有一种感觉,大多数人真的想在这里,是消除只是一个发生尾随换行符的,无论是\r\n\n仅此而已。

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

?:创建一个非捕获组。)

(顺便说一句,这不是做什么'...'.rstrip('\n', '').rstrip('\r', ''),其他人可能不会在这个线程上绊脚石。 str.rstrip剥离掉尽可能多的尾随字符,因此,像这样的字符串foo\n\n\n会导致的误报,foo而您可能想保留除去尾随单个后的其他换行符。)


您甚至可以使用regex跳过非捕获组,即使是您的最终方法r'\r?\n$'。可能更有效,因为正则表达式引擎很难优化轮换。还请注意,如果您打算多次执行此操作,那么对表达式进行一次处理(特别是与其他re用途混合使用)将明显更快(re.compile然后使用sub编译的regex对象的方法);模块功能是Python级别的,并且首先检查缓存中是否有已编译的正则表达式(如果缺少则创建/缓存),然后调用匹配方法;跳过查找会有所帮助。
ShadowRanger

1
另外,请注意:由于您要尝试\n直接匹配,因此可能要使用\Zover $(或只是match \r?$,因为$隐式可以在字符串末尾的换行符之前进行匹配)。
ShadowRanger

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

我需要的例子!因此,rstrip(“ \ r \ n”)将在行尾以任意组合剥离'\ n'和'\ r'!
Agostino

@Agostino无需提供"\r\n"例如:' spacious \n\r\n\r \n\n'.rstrip()产生' spacious'
olibre '17

2
@olibre您建议的代码还将去除其他空格/空格字符,而这可能不是您所需要的。实际上,我只需要剥离eol字符的组合即可。不过,感谢您指出这一点。
阿哥斯蒂诺

4

只需使用:

line = line.rstrip("\n")

要么

line = line.strip("\n")

您不需要这些复杂的东西


2
请注意,这与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'

与正则表达式

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

替换\ n,\ t,\ r

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

与正则表达式

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

与加入

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

3

有三种类型的行结尾的,我们常遇到的问题:\n\r\r\n。中的一个相当简单的正则表达式re.sub,即r"\r?\n?$",能够将它们全部捕获。

(而且我们要抓住一切,对吗?)

import re

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

对于最后一个参数,我们将替换的出现次数限制为一次,从而在某种程度上模仿了chomp。例:

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)

...这里a == b == cTrue


您甚至不需要完整的正则表达式。rstrip("\r\n")是万能的。尝试print(text_2.rstrip('\r\n'))
Agostino

@Agostino:是的,因为这str.rstrip()可以解决问题。这取决于您的需求。该解决方案是专门为取得的情况下,当你只是需要删除最后一个"\n""\r""\r\n"但不是所有的人(如果有多个"\n"字符串中)。re.sub(r"\r?\n?$", "", text_1, 1)返回"hellothere\n\n"text_1.rstrip("\r\n")返回"hellothere"不同的字符串。
互联网上的互联网

我想说的是:str.strip()有时候,这是一个万能的问题。
互联网

1

如果您担心速度(例如,您有很长的字符串列表)并且知道换行符char的性质,则字符串切片实际上比rstrip快。进行一点测试以说明这一点:

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

输出:

Method 1: 3.92700004578
Method 2: 6.73000001907

我知道我应该在函数内部使用“全局循环”,但这也可以。
史蒂芬·米勒

这个测试是错误的,不公平的。在method1你刚砍的最后一个字符,无论什么时候,在method2.rstrip()首先检查,如果字符串的结尾包含不需要的字符,扒他们,只有当一些被发现。请对字符进行一些检查method1并重新测试!
spky

正如我在答案的简介中所说:如果您知道换行符char的性质,那么这很有用。如果不这样做,显然您需要实现某种字符检查-或仅使用rstrip。我并不是想对rstrip感到“不公平”,而只是说明一个并非微不足道的差异,在某些情况下可能值得考虑。
Stephen Miller

1

这将同时适用于Windows和Linux(如果您只寻求re解决方案,那么re sub会有点贵)

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


3
为什么re.search在您只需要的地方使用re.sub
wjandrea

0

首先分割线,然后通过您喜欢的任何分隔符将它们连接起来:

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

应该像魅力一样工作。


-1

一网打尽:

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

5
rstrip不采用正则表达式。"hi|||\n\n".rstrip("\r|\n")返回"hi"
Flimm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.