Как я могу удалить завершающий перевод строки в Python? - PullRequest
1498 голосов
/ 08 ноября 2008

Что такое Python-эквивалент функции Perl chomp, которая удаляет последний символ строки, если она является новой строкой?

Ответы [ 26 ]

20 голосов
/ 27 апреля 2011

Осторожно с "foo".rstrip(os.linesep): Это только скомпрометирует символы новой строки для платформы, где выполняется ваш Python. Представьте, что вы изменяете строки файла Windows под Linux, например:

$ 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"), как сказал Майк выше.

19 голосов
/ 23 октября 2013

Пример в документации Python просто использует line.strip().

Функция Perl chomp удаляет одну последовательность разрыва строки из конца строки, только если она действительно есть.

Вот как я планирую сделать это в Python, если process концептуально является функцией, которая мне нужна, чтобы сделать что-то полезное для каждой строки из этого файла:

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)
17 голосов
/ 23 апреля 2011

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'
14 голосов
/ 03 июля 2009

Я не программирую на Python, но я наткнулся на FAQ на python.org, защищающем S.rstrip ("\ r \ n") для Python 2.2 или более поздней версии.

10 голосов
/ 20 января 2014
import re

r_unwanted = re.compile("[\n\t\r]")
r_unwanted.sub("", your_text)
8 голосов
/ 30 ноября 2011

обходное решение для особого случая:

если символ новой строки является последним символом (как в случае с большинством файловых вводов), то для любого элемента в коллекции вы можете индексировать следующим образом:

foobar= foobar[:-1]

, чтобы вырезать ваш символ новой строки.

8 голосов
/ 11 октября 2013

Если ваш вопрос состоит в том, чтобы очистить все разрывы строк в многострочном объекте str (oldstr), вы можете разбить его на список в соответствии с разделителем '\ n', а затем присоединить этот список к новой строке (newstr). ).

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

6 голосов
/ 26 апреля 2017

Похоже, идеального аналога для perl's chomp не существует. В частности, rstrip не может обрабатывать многосимвольные разделители новой строки, такие как \r\n. Однако, splitline делает , как указано здесь . После моего ответа на другой вопрос вы можете объединить объединить и splitline , чтобы удалить / заменить все новые строки из строки s:

''.join(s.splitlines())

Следующий код удаляет ровно один трейлинг символ новой строки (как я полагаю, chomp). Передача True в качестве аргумента keepends для разделенных линий сохраняет разделители. Затем снова вызывается splitline, чтобы удалить разделители только на последней «строке»:

def chomp(s):
    if len(s):
        lines = s.splitlines(True)
        last = lines.pop()
        return ''.join(lines + last.splitlines())
    else:
        return ''
6 голосов
/ 11 января 2015

Мне удобно иметь возможность получать строки с шипами в итераторе параллельно с тем, как можно получать линии без шипования из файлового объекта. Вы можете сделать это с помощью следующего кода:

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)
5 голосов
/ 27 июля 2017

Я поднимаю свой ответ на основе регулярных выражений от ответа, который я разместил ранее в комментариях к другому ответу. Я думаю, что использование 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, тогда как вы, возможно, захотите сохранить другие новые строки после удаления одного завершающего.)

...