Як розділити багаторядковий рядок на кілька рядків?


287

У мене є багаторядковий рядковий літерал, який я хочу зробити в кожному рядку, наприклад:

inputString = """Line 1
Line 2
Line 3"""

Я хочу зробити щось подібне:

for line in inputString:
    doStuff()

Відповіді:


437
inputString.splitlines()

Дасть вам список з кожним елементом, splitlines()метод призначений для розділення кожного рядка на елемент списку.


12
+1. Я думаю, що це приємніше, ніж прийняте рішення, оскільки воно не возиться з роздільником рядків прямо. Все це просто працює з виділеним методом API!
lpapp

12
@lpapp, я повністю згоден. splitlines () є семантично (і функціонально, оскільки він використовує універсальні нові рядки та не містить порожнього рядка), ніж split ('\ n'). Тоді (2008 р.) Я був лише новачком Pythonista, і хапаючи, хоча в моїх сценаріях зараз видно, що я теж використовую сплінки () майже виключно. Тому я видаляю свою 104-бальну відповідь ( * sob ... * ) і замість цього схвалюю.
efotinis

18
Це також робить ''.splitlines() == [], ['']як не так ''.split('\n').
праворуч

198

Як казали інші:

inputString.split('\n')  # --> ['Line 1', 'Line 2', 'Line 3']

Це ідентично вищесказаному, але функції модульного рядка застаріли і їх слід уникати:

import string
string.split(inputString, '\n')  # --> ['Line 1', 'Line 2', 'Line 3']

Крім того, якщо ви хочете, щоб кожен рядок включав послідовність розриву (CR, LF, CRLF), використовуйте splitlinesметод з Trueаргументом:

inputString.splitlines(True)  # --> ['Line 1\n', 'Line 2\n', 'Line 3']

12
Це буде працювати лише в системах, які використовують "\ n" як термінатор лінії.
Джеремі Кантрелл

20
@Jeremy: Потрійні літералі рядків завжди використовують '\ n' EOL, незалежно від платформи. Так само читання файлів у текстовому режимі.
efotinis

16
inputString.split(os.linesep)буде використовувати конкретний лінійний термінатор для платформи.
Джеймс

10
Дивно, що ця відповідь настільки схвальна. Жорстке кодування '\ n' - це погана ідея, але навіть якщо ви замість цього використовуєте os.linesep, у вас виникнуть проблеми з кінцями рядків Windows на Linux та навпаки тощо. ймовірно, менш поширений спосіб його використання ...
lpapp

4
Поєднання субоптимального методу, застарілого методу та надмірної варіації оптимального методу.
jwg

50

Використовуйтеstr.splitlines() .

splitlines()обробляє нові лінії правильно, на відміну від split("\n").

Він також має перевагу, згадану @efotinis, в тому, що необов'язково включати символ нового рядка в результат розбиття, коли викликається Trueаргументом.


Детальне пояснення того, чому не слід використовувати split("\n"):

\n, в Python, являє собою розрив рядків Unix (десятковий код ASCII 10), незалежно від платформи, де ви його запускаєте. Однак представлення рядкової лінії залежить від платформи . У Windows \nє два символи ( CRта LFдесяткових кодів ASCII 13 і 10, AKA \rі \n), тоді як на будь-якому сучасному Unix (включаючи OS X) це єдиний символ LF.

print, наприклад, працює правильно, навіть якщо у вас є рядок із закінченнями рядків, які не відповідають вашій платформі:

>>> print " a \n b \r\n c "
 a 
 b 
 c

Однак явне розділення на "\ n" призведе до поведінки, залежно від платформи:

>>> " a \n b \r\n c ".split("\n")
[' a ', ' b \r', ' c ']

Навіть якщо ви використовуєте os.linesep, він розділиться лише відповідно до роздільника нового рядка на вашій платформі, і вийде з ладу, якщо ви обробляєте текст, створений на інших платформах, або з голою \n:

>>> " a \n b \r\n c ".split(os.linesep)
[' a \n b ', ' c ']

splitlines вирішує всі ці проблеми:

>>> " a \n b \r\n c ".splitlines()
[' a ', ' b ', ' c ']

Читання файлів у текстовому режимі частково пом’якшує проблему представлення нового рядка, оскільки вона перетворює Python \nв представлення нового рядка платформи. Однак текстовий режим існує лише в Windows. У системах Unix всі файли відкриваються у двійковому режимі, тому використання split('\n')в системі UNIX з файлом Windows призведе до небажаної поведінки. Крім того, незвично обробляти рядки з потенційно різними новими рядками з інших джерел, наприклад, з сокета.


Порівняння не є справедливим, оскільки ви також можете використовувати спліт (os.linesep), щоб уникнути біт платформи.
lpapp

6
@lpapp зауважте, що splitlinesбуде розділено на будь-який рядок, що закінчується. split(os.linesep)не вдасться прочитати файл Windows в unix, наприклад
goncalopp

1
Ще одна причина використання розділених ліній у моєму випадку, дякую. Я дав +1. Я особисто навіть включив цю інформацію у коментарі до вашої відповіді.
lpapp

20

У цьому конкретному випадку може бути зайвим, але інший варіант передбачає використання StringIOдля створення файлоподібного об’єкта

for line in StringIO.StringIO(inputString):
    doStuff()

Так, це самий ідіоматичний, самий Python-ic підхід.
Парамагнітний круасан

4
Перевага цього методу в порівнянні з тим str.split, що не потрібно виділяти пам'ять (він читає рядок на місці). Недоліком є ​​те, що це набагато повільніше, якщо ви користуєтесьStringIO (приблизно 50 разів). Якщо ви користуєтеся cStringIO, однак, це приблизно в 2 рази швидше
goncalopp

2x швидше, ніж що?
Ірина Рапопорт

1
@IrinaRapoport, cStringIO у 2 рази швидше, ніж StringIO
iruvar

1

Оригінальна публікація запитується для коду, який друкує деякі рядки (якщо вони відповідають дійсності для певної умови) плюс наступний рядок. Моєю реалізацією було б таке:

text = """1 sfasdf
asdfasdf
2 sfasdf
asdfgadfg
1 asfasdf
sdfasdgf
"""

text = text.splitlines()
rows_to_print = {}

for line in range(len(text)):
    if text[line][0] == '1':
        rows_to_print = rows_to_print | {line, line + 1}

rows_to_print = sorted(list(rows_to_print))

for i in rows_to_print:
    print(text[i])

0

Я б хотів, щоб коментарі мали правильне форматування тексту коду, тому що я думаю, що відповідь @ 1_CR потребує більше ударів, і я хотів би доповнити його відповідь. У будь-якому випадку, він привів мене до наступної техніки; вона буде використовувати cStringIO, якщо вона доступна (АЛЕ ПРИМІТКА: cStringIO і StringIO не однакові , тому що ви не можете підклас cStringIO ... це вбудований ... але для основних операцій синтаксис буде ідентичним, тому ви можете це зробити ):

try:
    import cStringIO
    StringIO = cStringIO
except ImportError:
    import StringIO

for line in StringIO.StringIO(variable_with_multiline_string):
    pass
print line.strip()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.