如何删除python中的末尾换行符?

How can I remove a trailing newline in Python?

Perl的chomp函数的python等价物是什么?如果字符串是换行符,它将删除字符串的最后一个字符。


尝试方法rstrip()(参见doc python 2和python 3)

1
2
3
>>> 'test string
'
.rstrip()
'test string'

python的rstrip()方法默认情况下会去掉所有类型的尾随空格,而不仅仅是Perl对chomp所做的换行操作。

1
2
3
4
5
6
7
8
9
>>> 'test string
 



 

'
.rstrip()
'test string'

只删除换行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> 'test string
 



 

'
.rstrip('
'
)
'test string
 



 '

还有方法lstrip()strip()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>> s ="  


 
  abc   def


 
 "

>>> s.strip()
'abc   def'
>>> s.lstrip()
'abc   def


 
  '

>>> s.rstrip()
'  


 
  abc   def'


我要说的是"pythonic"方法,在不拖尾换行符的情况下获取行是splitlines()。

1
2
3
4
5
6
7
>>> text ="line 1
line 2

line 3
line 4"

>>> text.splitlines()
['line 1', 'line 2', 'line 3', 'line 4']


去除行尾(eol)字符的标准方法是使用字符串r strip()方法删除任何尾随的
或字符。以下是Mac、Windows和Unix eol字符的示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> 'Mac EOL
'
.rstrip('

'
)
'Mac EOL'
>>> 'Windows EOL

'
.rstrip('

'
)
'Windows EOL'
>>> 'Unix EOL
'
.rstrip('

'
)
'Unix EOL'

使用'
'作为r strip的参数意味着它将除去'
'或''的任何尾随组合。这就是为什么它适用于上述三种情况。

这种细微差别在罕见的情况下很重要。例如,我曾经必须处理一个包含HL7消息的文本文件。HL7标准要求尾随的'
'作为其EOL字符。我使用此消息的Windows计算机已附加了自己的
"eol字符。因此,每行的结尾看起来像'

'。使用rstrip("
")可以去掉整个'

',这不是我想要的。在这种情况下,我只是简单地切掉最后两个字符。

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

1
2
3
4
5
6
>>>"Hello


"
.rstrip("
"
)
"Hello"


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

1
2
3
4
$x="a
"
;

chomp $x

结果$x"a"

但在Python:

1
2
3
4
x="a
"


x.rstrip()

也就是说,x的值仍然是"a
"
。即使是x=x.rstrip()也不总是给出相同的结果,因为它从字符串的末尾去掉了所有的空白,而不只是一个换行符。


我可能会用这样的东西:

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

我认为rstrip("
")
的问题在于,您可能需要确保行分隔符是可移植的。(有传言说一些过时的系统使用"

"。另一个问题是,rstrip将删除重复出现的空白。希望os.linesep包含正确的字符。以上这些对我有用。


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


1
s = s.rstrip()

将删除字符串s末尾的所有换行符。由于rstrip返回新字符串而不是修改原始字符串,因此需要进行赋值。


这将为"行终止符复制Perl的chomp(减去数组上的行为):

1
2
3
4
5
6
7
8
def chomp(x):
    if x.endswith("

"
): return x[:-2]
    if x.endswith("
"
) or x.endswith("
"
): return x[:-1]
    return x

(注意:它不修改字符串'in-place';它不删除多余的尾随空格;考虑
)


1
2
3
4
5
6
7
"line 1
line 2

..."
.replace('
'
, '').replace('
'
, '')
>>> 'line 1line 2...'

或者你总是能在regexps上变得更有趣:)

玩得高兴!


您可以使用条带:

1
line = line.strip()

演示:

1
2
3
4
5
6
>>>"

 hello world

"
.strip()
'hello world'


小心使用"foo".rstrip(os.linesep):这只会为执行python的平台选择换行符。假设您在Linux下处理Windows文件的行,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ 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

"
.rstrip(os.linesep)
'foo
'

>>>

"foo".rstrip("

")代替,正如迈克上面所说的。


python文档中的一个示例只使用line.strip()

Perl的chomp函数只在字符串实际存在的情况下从字符串的末尾删除一个换行符序列。

下面是我计划在python中实现这一点的方法,如果process在概念上是我需要的函数,以便对该文件中的每一行执行一些有用的操作:

1
2
3
4
5
6
7
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和chomp做的不一样。阅读http://perldoc.perl.org/functions/chomp.html,发现chomp确实非常复杂。

然而,我的主要观点是chomp最多删除1行结尾,而rstrip将删除尽可能多的行。

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

1
2
3
4
>>> 'foo

'
.rstrip(os.linesep)
'foo'

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

1
2
3
4
5
>>> re.sub(os.linesep + r'\Z','','foo

'
)
'foo
'


我没有用python编程,但我在python.org上遇到了一个常见问题解答,它提倡S.rstrip("
")用于python 2.2或更高版本。


1
2
3
4
5
6
import re

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


针对特殊情况的解决方案:

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

1
foobar= foobar[:-1]

把你的换行符切掉。


如果您的问题是清除多行str对象(oldstr)中的所有换行符,则可以根据分隔符'将其拆分为一个列表,然后将此列表加入到新的str(new str)。

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


我发现能够通过迭代器获取被选中的行很方便,这与从文件对象获取未被选中的行的方式是平行的。您可以使用以下代码执行此操作:

1
2
3
4
def chomped_lines(it):
    return map(operator.methodcaller('rstrip', '

'
), it)

样品使用情况:

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


似乎没有一个完美的Perl Chomp模拟。特别是,rstrip不能处理多字符换行符,如

。然而,分割线就像这里指出的那样。根据我对另一个问题的回答,您可以将连接线和拆分线组合在一起,以从字符串s中删除/替换所有新行:

1
''.join(s.splitlines())

下面只删除了一条尾随的换行符(我相信Chomp会这样做)。将True作为keepends参数传递给splitlines,保留定界符。然后,再次调用splitlines以删除最后一个"line"上的分隔符:

1
2
3
4
5
6
7
def chomp(s):
    if len(s):
        lines = s.splitlines(True)
        last = lines.pop()
        return ''.join(lines + last.splitlines())
    else:
        return ''


我正在从先前在另一个答案的评论中发布的基于正则表达式的答案中冒泡出来。我认为使用restr.rstrip更明确地解决了这个问题。

1
>>> import re

如果要删除一个或多个尾随换行符:

1
2
3
4
5
6
7
8
>>> re.sub(r'[

]+$'
, '', '
x

'
)
'
x'

如果要在所有位置删除换行符(不仅仅是尾随字符):

1
2
3
4
5
6
7
>>> re.sub(r'[

]+'
, '', '
x

'
)
'x'

如果只想删除1-2个尾随换行符字符(即

)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
>>> re.sub(r'[

]{1,2}$'
, '', '
x



'
)
'
x
'

>>> re.sub(r'[

]{1,2}$'
, '', '
x


'
)
'
x
'

>>> re.sub(r'[

]{1,2}$'
, '', '
x

'
)
'
x'

我有一种感觉,在这里大多数人真正想要的是去掉一个尾随的换行符,要么是

,要么是
,什么都没有。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
>>> re.sub(r'(?:

|
)$'
, '', '
x

'
, count=1)
'
x
'

>>> re.sub(r'(?:

|
)$'
, '', '
x



'
, count=1)
'
x

'

>>> re.sub(r'(?:

|
)$'
, '', '
x

'
, count=1)
'
x'

>>> re.sub(r'(?:

|
)$'
, '', '
x
'
, count=1)
'
x'

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

(顺便说一句,这不是'...'.rstrip('
', '').rstrip('
', '')
所做的,其他人在这条线上绊倒也不清楚。str.rstrip尽可能多地去掉尾随字符,因此像foo

这样的字符串将导致foo的假阳性,而在去掉单个尾随字符后,您可能希望保留其他新行。)


只需使用:

1
2
line = line.rstrip("
"
)

1
2
line = line.strip("
"
)

你不需要这些复杂的东西


1
2
3
4
5
6
7
8
>>> '   spacious   '.rstrip()
'   spacious'
>>>"AABAA".rstrip("A")
  'AAB'
>>>"ABBA".rstrip("AB") # both AB and BA are stripped
   ''
>>>"ABCABBA".rstrip("AB")
   'ABC'


我们通常会遇到三种类型的行尾:

。在re.sub中,一个相当简单的正则表达式,即r"
?
?$"
能够捕获所有的元素。

(我们要抓住他们,对吗?)

1
2
3
4
5
import re

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

最后一个论点是,我们将替换的发生次数限制为一次,在某种程度上模仿chomp。例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import re

text_1 ="hellothere


"

text_2 ="hellothere


"

text_3 ="hellothere



"


a = re.sub(r"
?
?$"
,"", text_1, 1)
b = re.sub(r"
?
?$"
,"", text_2, 1)
c = re.sub(r"
?
?$"
,"", text_3, 1)

…其中a == b == cTrue


如果你关心速度(比如你有一个很长的字符串列表),并且你知道换行符的性质,那么字符串切片实际上比rstrip快。一个小测试来说明这一点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import time

loops = 50000000

def method1(loops=loops):
    test_string = 'num
'

    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
'

    t0 = time.time()
    for num in xrange(loops):
        out_sting = test_string.rstrip()
    t1 = time.time()
    print('Method 2: ' + str(t1 - t0))

method1()
method2()

输出:

1
2
Method 1: 3.92700004578
Method 2: 6.73000001907


这对Windows和Linux都适用(如果您只想寻找RE解决方案,那么Re-Sub有点贵)

1
2
3
4
5
6
7
import re
if re.search("(\
|)\
$"
, line):
    line = re.sub("(\
|)\
$"
,"", line)


一举一动:

1
2
3
line = line.rstrip('
|
'
)