Как я могу удалить завершающий перевод строки?


1689

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


2
Суперсет: любая строка вместо только новой строки: stackoverflow.com/questions/1038824/…
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

3
Ответ A +: если это произошло из-за того, что вы забыли open()файл с соответствующим параметром 'newline = ...' для вашей платформы (универсальная поддержка новой строки), вам может не потребоваться его явное удаление.
smci

Ответы:


1868

Попробуйте метод rstrip()(см. Документ Python 2 и Python 3 )

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

rstrip()Метод Python по умолчанию удаляет все виды конечных пробелов, а не только одну новую строку, как это делает 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), и она изменчива. Есть ли способ удалить это значение только один раз из конца строки?
Брайан Д. Фой

5
Брайан Д. Фой: У Python нет разделителя входных записей, как у awk и Perl.
Питер Хоси

7
@csde_rats, это не так: OS X использует \nдля перехода на новую строку, как Unix. (До OS X MacOS использовался \rкак разделитель строк, но это закончилось 10 лет назад.)
skue

21
@briandfoy Python имеет встроенную поддержку новых строк (только при чтении, а не при записи). Вы открываете файл в режиме «U» или «rU», а затем, независимо от Windows, Linux, Mac, независимо от того, к тому времени, когда текст достигает кода вашего Python, любой стиль новой строки заменяется на «\ n». Смотрите: python.org/dev/peps/pep-0278
AlcubierreDrive

12
Я собираюсь продолжить и объяснить это, потому что я нуб, и я провел некоторое время, размышляя, почему это не работает. .strip()не изменяет строку (вероятно, имеет отношение к неизменным строкам). Если не в командной строке, вы захотите"string = string.strip()"
Script Kitty

158

И я бы сказал, что «питонный» способ получить строки без завершающих символов новой строки - это splitlines ().

>>> text = "line 1\nline 2\r\nline 3\nline 4"
>>> text.splitlines()
['line 1', 'line 2', 'line 3', 'line 4']


146

Канонический способ удаления символов конца строки (EOL) заключается в использовании метода string 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 ', а это не то, что я хотел. В этом случае я просто отрезал последние два символа вместо этого.

Обратите внимание, что в отличие от chompфункции Perl , это удалит все указанные символы в конце строки, а не только один:

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

7
Обратите внимание, что современные приложения Mac OS X используют \ n. Только старые приложения Carbon, изначально написанные для Mac OS, используют \ r.
Питер Хоси

2
Благодарю за разъяснение. Конечно, rstrip ('\ r \ n') все еще работает и в этом случае.
Майк

13
Также os.linesepесть последовательность EOL для текущей ОС.
Эли Коллинз

Это лучший ответ: он удаляет только новые строки и делает это правильно для самых распространенных платформ.
Кевинарпе

плюс +1 За использование \nи\r
fechnert

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 удаляет только одну новую
строку

50

Я мог бы использовать что-то вроде этого:

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

Думаю, проблема в rstrip("\n")том, что вы, вероятно, захотите убедиться, что разделитель строк переносим. (по слухам, некоторые устаревшие системы используются "\r\n"). Другая проблема заключается в том, rstripчто удалит повторяющиеся пробелы. Надеюсь, os.linesepбудет содержать правильные символы. вышеупомянутое работает для меня.


12
Однако это не сработает, если вы пытаетесь очистить пользовательский контент в веб-приложении. Пользовательский контент может поступать из любого источника и содержать любые символы новой строки.
apiguy

2
Хорошая мысль, за исключением того, что вы можете обрабатывать «чужие» файлы (из устаревших систем) на вашей современной ОС.
ChuckCottrill

1
Помните также, что если вы читаете файл в текстовом режиме, это также не будет работать в системе Windows, потому что завершающий символ всегда будет преобразован в '\ n'.
Безумный физик

@MadPhysicist Вы правы, что он конвертирует его, но он все еще работает, потому что он такой же, как rstrip('\r\n')и rstrip()удалит все символы в аргументе.
dtauxe

41

Вы можете использовать line = line.rstrip('\n'). Это уберет все новые строки с конца строки, а не только один.


35
s = s.rstrip()

удалит все символы новой строки в конце строки s. Назначение необходимо, потому что rstripвозвращает новую строку вместо изменения исходной строки.


33

Это будет точно повторять chomp perl (минус поведение массивов) для терминатора строки "\ 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

(Примечание: он не изменяет строку «на месте»; он не удаляет лишние конечные пробелы; учитывает \ r \ n)


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

или вы всегда можете получить geekier с регулярными выражениями :)

радоваться, веселиться!


Это помогло мне быстро превратить текстовый файл с окончаниями строк в одну строку текста. Я новичок, поэтому не уверен, что есть лучший способ сделать это, но это сработало, спасибо! (Кажется, Газа работает только с конца, а не изнутри)
Стив Кох

2
Почему бы просто не использовать одно выражение замены, как .replace('\n|\r', '')?
июня

2
На всякий случай, если кто-то еще захочет использовать идею из @DoorknobofSnow, использовать модуль regex будет просто небольшим изменением: import re re.sub('\n|\r', '', '\nx\n\r\n')==> 'x'.
Тейлор Эдмистон

Использование этого метода и метода регулярных выражений, как упомянуто @TaylorEdmiston, должно быть правильным ответом.
Bhargav

@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 может быть получено более близкое приближение типичного использования chomp для Perl, например:

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

2
Слава, ты единственный, кто указал на эту очень важную деталь. Однако, как отмечалось выше, использование os.linesep не будет работать, если вы читаете файлы из другой системы. Это может занять немного больше работы в Python, фактически проверяя конец строки.
brianmearns

19

Осторожно с "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")вместо этого, как говорит Майк выше.


Еще одна вещь, которую стоит отметить, это то, что она удаляет не более одной новой строки, но в отличие от всех новых строк chomp.
Flimm

19

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

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

Вот как я планирую сделать это в 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)

2
И, наконец, ответ, который удаляет его только один раз (например, фактический chomp ...) и является переносимым для ОС!
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

13

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


10
import re

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

2
Это также приведет к удалению пробела табуляции, который не запрашивается в исходном вопросе. (Из-за символа \ t)
NoahR

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.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).
ShadowRanger

8

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

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

foobar= foobar[:-1]

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


3
Иногда перевод строки не последний символ, но последние из них, особенно на окнах, как уже отмечалось.
Cacovsky

8

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

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


7

Похоже, нет идеального аналога для perl's chomp . В частности, rstrip не может обрабатывать многосимвольные разделители новой строки, такие как \r\n. Тем не менее, 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 ''

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


Вы можете пропустить группу без захвата, даже для вашего окончательного подхода, с помощью регулярного выражения r'\r?\n$'. Вероятно, более эффективный, так как двигателям регулярных выражений труднее оптимизировать изменения. Также обратите внимание, что если вы собираетесь делать это много раз, оно будет значительно быстрее (особенно если вы смешиваете с другими reиспользованиями) re.compileвыражение сразу, затем используйте subметод скомпилированного объекта регулярного выражения; Функции модуля находятся на уровне Python и сначала проверяют кэш на наличие скомпилированных регулярных выражений (в случае отсутствия / создания / кэширования), а затем вызывают соответствующий метод; Пропуск этого поиска помогает.
ShadowRanger

1
Кроме того, примечание: поскольку вы пытаетесь сопоставить \nнапрямую, вы можете использовать \Zболее $(или просто сопоставить \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 Не нужно предоставлять "\r\n"Например: ' spacious \n\r\n\r \n\n'.rstrip()производит' spacious'
olibre

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 == cнаходится True.


Вам даже не нужны полноценные регулярные выражения. rstrip("\r\n")это всеобъемлющее. Попробуй print(text_2.rstrip('\r\n')).
Агостино

@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

Если вас беспокоит скорость (скажем, у вас есть длинный список строк), и вы знаете природу символа новой строки, срезание строк на самом деле быстрее, чем 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

Как я сказал во вступлении к ответу: если вы знаете природу символа новой строки, то это полезно. Если вы этого не сделаете, то да, вам, очевидно, нужно реализовать какую-то проверку символов или просто использовать rstrip. Я не хотел быть «несправедливым» по отношению к людям, а просто иллюстрировал не столь незначительную разницу, которую, возможно, стоит рассмотреть в некоторых ситуациях.
Стивен Миллер

1

Это будет работать как для Windows, так и для Linux (немного дороже с re sub, если вы ищете только re решение)

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.