Làm cách nào để chia chuỗi nhiều dòng thành nhiều dòng?


287

Tôi có một chuỗi ký tự nhiều dòng mà tôi muốn thực hiện một thao tác trên mỗi dòng, như vậy:

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

Tôi muốn làm một cái gì đó như sau:

for line in inputString:
    doStuff()

Câu trả lời:


437
inputString.splitlines()

Sẽ cung cấp cho bạn một danh sách với mỗi mục, splitlines()phương thức được thiết kế để phân chia từng dòng thành một thành phần danh sách.


12
+1. Tôi nghĩ rằng điều này là tốt hơn so với giải pháp được chấp nhận bởi vì nó không gây rối với phân cách dòng rõ ràng. Tất cả chỉ hoạt động với một phương thức API chuyên dụng!
lpapp

12
@lpapp, tôi hoàn toàn đồng ý. splitlines () là về mặt ngữ nghĩa (và về mặt chức năng, vì nó sử dụng các dòng mới phổ quát và bỏ qua một dòng trống ở cuối) tốt hơn so với split ('\ n'). Trước đó (2008) Tôi chỉ là một người mới chơi Pythonista và đang tham gia mặc dù các tập lệnh của tôi bây giờ cho thấy rằng tôi cũng đang sử dụng splitlines () gần như độc quyền. Do đó, tôi đang xóa câu trả lời 104 điểm của mình ( * nức nở ... * ) và thay vào đó sẽ xác nhận câu trả lời này.
efotinis

18
Điều này cũng làm ''.splitlines() == [], không ['']như với ''.split('\n').
đúng

198

Giống như những người khác nói:

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

Điều này giống hệt như ở trên, nhưng các chức năng của mô-đun chuỗi không được dùng nữa và nên tránh:

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

Ngoài ra, nếu bạn muốn mỗi dòng bao gồm chuỗi ngắt (CR, LF, CRLF), hãy sử dụng splitlinesphương thức với một Trueđối số:

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

12
Điều này sẽ chỉ hoạt động trên các hệ thống sử dụng '\ n' làm đầu cuối dòng.
Jeremy Cantrell

20
@Jeremy: Các chuỗi ký tự ba trích dẫn luôn sử dụng EOL '\ n', bất kể nền tảng. Vì vậy, các tập tin đọc trong chế độ văn bản.
efotinis

16
inputString.split(os.linesep)sẽ sử dụng bộ kết thúc dòng cụ thể nền tảng.
James

10
Thật kỳ lạ khi câu trả lời này được nâng cao như vậy. Mã hóa cứng '\ n' là một ý tưởng tồi, nhưng ngay cả khi bạn sử dụng os.linesep thay vì đó, bạn sẽ gặp vấn đề với các dòng cửa sổ kết thúc trên Linux và ngược lại, v.v. Ngoài ra, nó đang quảng bá các dòng chia nhỏ với đối số True. có thể là cách sử dụng ít phổ biến hơn ...
lpapp

4
Một sự kết hợp của một phương pháp tối ưu, một phương pháp không dùng nữa và một biến thể dự phòng của phương pháp tối ưu.
JWG

50

Sử dụngstr.splitlines() .

splitlines()xử lý các dòng mới đúng cách, không giống như split("\n").

Nó cũng có lợi thế được đề cập bởi @efotinis về tùy chọn bao gồm ký tự dòng mới trong kết quả phân tách khi được gọi bằng một Trueđối số.


Giải thích chi tiết về lý do bạn không nên sử dụng split("\n"):

\n, trong Python, đại diện cho ngắt dòng Unix (mã thập phân ASCII 10), độc lập với nền tảng nơi bạn chạy nó. Tuy nhiên, đại diện linebreak phụ thuộc vào nền tảng . Trên Windows, \ncó hai ký tự CRLF(mã thập phân ASCII 13 và 10, AKA \r\n), trong khi trên bất kỳ Unix hiện đại nào (bao gồm cả OS X), đó là ký tự đơn LF.

print, ví dụ, hoạt động chính xác ngay cả khi bạn có một chuỗi có kết thúc dòng không khớp với nền tảng của bạn:

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

Tuy nhiên, việc phân tách rõ ràng trên "\ n", sẽ mang lại hành vi phụ thuộc vào nền tảng:

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

Ngay cả khi bạn sử dụng os.linesep, nó sẽ chỉ phân tách theo dấu phân cách dòng mới trên nền tảng của bạn và sẽ thất bại nếu bạn đang xử lý văn bản được tạo trong các nền tảng khác hoặc với mức trần \n:

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

splitlines giải quyết tất cả những vấn đề này:

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

Đọc các tệp trong chế độ văn bản sẽ giảm bớt một phần vấn đề biểu diễn dòng mới, vì nó chuyển đổi Python \nthành biểu diễn dòng mới của nền tảng. Tuy nhiên, chế độ văn bản chỉ tồn tại trên Windows. Trên các hệ thống Unix, tất cả các tệp được mở ở chế độ nhị phân, do đó, sử dụng split('\n')trong hệ thống UNIX với tệp Windows sẽ dẫn đến hành vi không mong muốn. Ngoài ra, không có gì lạ khi xử lý các chuỗi với các dòng mới có khả năng khác với các nguồn khác, chẳng hạn như từ một ổ cắm.


Việc so sánh là không công bằng vì bạn cũng có thể sử dụng split (os.linesep) để tránh bit cụ thể của nền tảng.
lpapp

6
@lpapp lưu ý rằng splitlinessẽ phân chia trên bất kỳ dòng kết thúc. split(os.linesep)sẽ thất bại khi đọc tệp windows trong unix, chẳng hạn
goncalopp

1
Một lý do khác để sử dụng splitlines trong trường hợp của tôi, cảm ơn. Tôi đã cho +1. Cá nhân tôi thậm chí sẽ kết hợp thông tin trong các ý kiến ​​vào câu trả lời của bạn.
lpapp

20

Có thể là quá mức cần thiết trong trường hợp cụ thể này nhưng một tùy chọn khác liên quan đến việc sử dụng StringIOđể tạo một đối tượng giống như tệp

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

Vâng, đây là cách tiếp cận thành ngữ nhất, Python-ic nhất.
Croissant Paramag từ

4
Một lợi thế của phương pháp này, khi so sánh với str.split, là không cần phân bổ bất kỳ bộ nhớ nào (nó đọc chuỗi tại chỗ). Một bất lợi là nó chậm hơn nhiều nếu bạn sử dụngStringIO (khoảng 50 lần). cStringIOTuy nhiên,
goncalopp

Nhanh gấp 2 lần?
Irina Rapoport

1
@IrinaRapoport, cStringIO nhanh gấp 2 lần StringIO
iruvar 17/07/18

1

Bài viết gốc được yêu cầu cho mã in một số hàng (nếu chúng đúng với một số điều kiện) cộng với hàng sau. Việc thực hiện của tôi sẽ là thế này:

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

Tôi muốn các bình luận có định dạng văn bản mã phù hợp, bởi vì tôi nghĩ câu trả lời của @ 1_CR cần nhiều sự va chạm hơn và tôi muốn làm tăng thêm câu trả lời của anh ấy. Dù sao, Ngài đã dẫn tôi đến kỹ thuật sau đây; nó sẽ sử dụng cStringIO nếu có (NHƯNG LƯU Ý: cStringIO và StringIO không giống nhau , vì bạn không thể phân lớp cStringIO ... nó được tích hợp sẵn ... nhưng đối với các hoạt động cơ bản, cú pháp sẽ giống hệt nhau, vì vậy bạn có thể thực hiện điều này ):

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

for line in StringIO.StringIO(variable_with_multiline_string):
    pass
print line.strip()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.