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()
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:
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.
''.splitlines() == []
, không ['']
như với ''.split('\n')
.
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 splitlines
phương thức với một True
đối số:
inputString.splitlines(True) # --> ['Line 1\n', 'Line 2\n', 'Line 3']
inputString.split(os.linesep)
sẽ sử dụng bộ kết thúc dòng cụ thể nền tảng.
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, \n
có hai ký tự CR
và LF
(mã thập phân ASCII 13 và 10, AKA \r
và \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 \n
thà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.
splitlines
sẽ 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
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()
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). cStringIO
Tuy nhiên,
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])
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()