Python与Perl chomp
函数等效吗?如果是换行符,它将删除字符串的最后一个字符?
open()
了平台上带有适当'newline = ...'参数的文件(通用换行支持),则可能不需要显式删除它。
Python与Perl chomp
函数等效吗?如果是换行符,它将删除字符串的最后一个字符?
open()
了平台上带有适当'newline = ...'参数的文件(通用换行支持),则可能不需要显式删除它。
Answers:
试用该方法rstrip()
(请参阅doc Python 2和Python 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'
\n
与Unix一样用于换行符。(在OS X之前,MacOS确实\r
用作行分隔符,但已于10年前终止。)
.strip()
不会更改字符串(可能与不可变的字符串有关)。如果不在命令行中,则需要"string = string.strip()"
我想说的是,在不尾随换行符的情况下获取行的“ pythonic”方法是splitlines()。
>>> text = "line 1\nline 2\r\nline 3\nline 4"
>>> text.splitlines()
['line 1', 'line 2', 'line 3', 'line 4']
删除行尾(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"
os.linesep
,其中包含当前操作系统的EOL序列。
\n
和\r
请注意,rstrip的行为与Perl的chomp()并不完全相同,因为它不会修改字符串。也就是说,在Perl中:
$x="a\n";
chomp $x
导致$x
存在"a"
。
但在Python中:
x="a\n"
x.rstrip()
将意味着价值x
是依旧 "a\n"
。甚至x=x.rstrip()
并不总是给出相同的结果,因为它从字符串的末尾去除所有空格,最多不只是一个换行符。
我可能会使用这样的东西:
import os
s = s.rstrip(os.linesep)
我认为问题rstrip("\n")
在于您可能需要确保行分隔符是可移植的。(有传闻说有些过时的系统要使用"\r\n"
)。另一个难题是,rstrip
它将去除重复的空白。希望os.linesep
将包含正确的字符。以上对我有用。
rstrip('\r\n')
并且rstrip()
会删除参数中的所有字符。
"line 1\nline 2\r\n...".replace('\n', '').replace('\r', '')
>>> 'line 1line 2...'
否则您总是可以通过regexp变得更加怪异:)
玩得开心!
.replace('\n|\r', '')
?
import re
re.sub('\n|\r', '', '\nx\n\r\n')
==> 'x'
。
您可以使用地带:
line = line.strip()
演示:
>>> "\n\n hello world \n\n".strip()
'hello world'
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'
注意"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
。
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)
import re
r_unwanted = re.compile("[\n\t\r]")
r_unwanted.sub("", your_text)
我发现能够通过迭代器获得短线很方便,这与从文件对象中获得短线的方式相似。您可以使用以下代码进行操作:
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.methodcaller
和map
(itertools.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)
。
特殊情况的解决方法:
如果换行符是最后一个字符(大多数文件输入都是这种情况),那么对于集合中的任何元素,您都可以按如下所示进行索引:
foobar= foobar[:-1]
切出换行符。
它看起来像没有用于Perl的一个完美的模拟格格。尤其是,rstrip无法处理多字符换行符分隔符,例如\r\n
。但是,分割线确实如此处指出。按照我对另一个问题的回答,您可以结合使用join和splitlines来删除/替换字符串中的所有换行符s
:
''.join(s.splitlines())
以下内容仅删除了一条尾随的换行符(我相信像排行一样)。True
将keepends
参数作为分割线传递时保留定界符。然后,再次调用splitlines以删除最后一个“行”上的分隔符:
def chomp(s):
if len(s):
lines = s.splitlines(True)
last = lines.pop()
return ''.join(lines + last.splitlines())
else:
return ''
我正在从先前在其他答案的评论中发布的答案中冒充基于正则表达式的答案。我认为使用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
而您可能想保留除去尾随单个后的其他换行符。)
r'\r?\n$'
。可能更有效,因为正则表达式引擎很难优化轮换。还请注意,如果您打算多次执行此操作,那么对表达式进行一次处理(特别是与其他re
用途混合使用)将明显更快(re.compile
然后使用sub
编译的regex对象的方法);模块功能是Python级别的,并且首先检查缓存中是否有已编译的正则表达式(如果缺少则创建/缓存),然后调用匹配方法;跳过查找会有所帮助。
\n
直接匹配,因此可能要使用\Z
over $
(或只是match \r?$
,因为$
隐式可以在字符串末尾的换行符之前进行匹配)。
>>> ' spacious '.rstrip()
' spacious'
>>> "AABAA".rstrip("A")
'AAB'
>>> "ABBA".rstrip("AB") # both AB and BA are stripped
''
>>> "ABCABBA".rstrip("AB")
'ABC'
"\r\n"
例如:' spacious \n\r\n\r \n\n'.rstrip()
产生' spacious'
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'
有三种类型的行结尾的,我们常遇到的问题:\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 == c
是True
。
rstrip("\r\n")
是万能的。尝试print(text_2.rstrip('\r\n'))
。
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()
有时候,这是一个万能的问题。
如果您担心速度(例如,您有很长的字符串列表)并且知道换行符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
并重新测试!
这将同时适用于Windows和Linux(如果您只寻求re解决方案,那么re sub会有点贵)
import re
if re.search("(\\r|)\\n$", line):
line = re.sub("(\\r|)\\n$", "", line)
re.search
在您只需要的地方使用re.sub
?