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

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'
Markus Jarderot
источник
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'). Это уберет все новые строки с конца строки, а не только один.

kiriloff
источник
35
s = s.rstrip()

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

SLEC
источник
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 с регулярными выражениями :)

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

mihaicc
источник
Это помогло мне быстро превратить текстовый файл с окончаниями строк в одну строку текста. Я новичок, поэтому не уверен, что есть лучший способ сделать это, но это сработало, спасибо! (Кажется, Газа работает только с конца, а не изнутри)
Стив Кох
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'
Hackaholic
источник
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'
ingydotnet
источник
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)
minopret
источник
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)
kuzzooroo
источник
Примечание: С 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]

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

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

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

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

Leozj
источник
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 ''
user3780389
источник
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.

Internetional
источник
Вам даже не нужны полноценные регулярные выражения. 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')
user4178860
источник
5
rstripне принимает регулярные выражения. "hi|||\n\n".rstrip("\r|\n")возвращается"hi"
Flimm