Câu trả lời:
Đầu tiên, mở tệp và nhận tất cả các dòng của bạn từ tệp. Sau đó mở lại tệp ở chế độ ghi và ghi lại các dòng của bạn, ngoại trừ dòng bạn muốn xóa:
with open("yourfile.txt", "r") as f:
lines = f.readlines()
with open("yourfile.txt", "w") as f:
for line in lines:
if line.strip("\n") != "nickname_to_delete":
f.write(line)
Bạn cần phải strip("\n")
so sánh ký tự dòng mới vì nếu tệp của bạn không kết thúc bằng ký tự dòng mới thì cuối cùng line
sẽ không có.
Giải pháp cho vấn đề này chỉ với một lần mở duy nhất:
with open("target.txt", "r+") as f:
d = f.readlines()
f.seek(0)
for i in d:
if i != "line you want to remove...":
f.write(i)
f.truncate()
Giải pháp này mở tệp ở chế độ r / w ("r +") và sử dụng tìm kiếm để đặt lại con trỏ f sau đó cắt bớt để xóa mọi thứ sau lần ghi cuối cùng.
for
vòng lặp, bạn sẽ kết thúc với một tệp bị ghi đè một phần, với các dòng trùng lặp hoặc một nửa dòng bị cắt. Bạn có thể muốn f.truncate()
ngay sau f.seek(0)
đó thay vào đó. Bằng cách đó, nếu bạn gặp lỗi, bạn sẽ kết thúc với một tệp không đầy đủ. Nhưng giải pháp thực sự (nếu bạn có dung lượng đĩa) là xuất ra tệp tạm thời và sau đó sử dụng os.replace()
hoặc pathlib.Path(temp_filename).replace(original_filename)
trao đổi nó với bản gốc sau khi mọi thứ đã thành công.
i.strip('\n') != "line you want to remove..."
như đã đề cập trong câu trả lời được chấp nhận, điều đó sẽ giải quyết hoàn hảo vấn đề của tôi. Bởi vì tôi i
đã không làm gì cho tôi
Tùy chọn tốt nhất và nhanh nhất, thay vì lưu trữ mọi thứ trong danh sách và mở lại tệp để ghi nó, theo ý kiến của tôi là viết lại tệp ở nơi khác.
with open("yourfile.txt", "r") as input:
with open("newfile.txt", "w") as output:
for line in input:
if line.strip("\n") != "nickname_to_delete":
output.write(line)
Đó là nó! Trong một vòng lặp và chỉ một bạn có thể làm điều tương tự. Nó sẽ nhanh hơn nhiều.
(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
os.replace
(mới trong python v 3.3) là đa nền tảng hơn so với một cuộc gọi hệ thống mv
.
Đây là một "ngã ba" từ câu trả lời của @Lother (mà tôi tin rằng nên được coi là câu trả lời đúng).
Đối với một tập tin như thế này:
$ cat file.txt
1: october rust
2: november rain
3: december snow
Cái ngã ba từ giải pháp này của Lother hoạt động tốt:
#!/usr/bin/python3.4
with open("file.txt","r+") as f:
new_f = f.readlines()
f.seek(0)
for line in new_f:
if "snow" not in line:
f.write(line)
f.truncate()
Cải tiến:
with open
, loại bỏ việc sử dụng f.close()
if/else
để đánh giá nếu chuỗi không có trong dòng hiện tạiVấn đề với việc đọc các dòng trong lần đầu tiên và thực hiện các thay đổi (xóa các dòng cụ thể) trong lần chuyển thứ hai là nếu kích thước tệp của bạn rất lớn, bạn sẽ hết RAM. Thay vào đó, một cách tiếp cận tốt hơn là đọc từng dòng một, và viết chúng thành một tệp riêng biệt, loại bỏ những thứ bạn không cần. Tôi đã chạy phương pháp này với các tệp lớn tới 12-50 GB và mức sử dụng RAM gần như không đổi. Chỉ các chu kỳ CPU hiển thị xử lý trong tiến trình.
Tôi thích cách tiếp cận fileinput như được giải thích trong câu trả lời này: Xóa một dòng khỏi tệp văn bản (python)
Ví dụ: tôi có một tệp có các dòng trống trong đó và tôi muốn xóa các dòng trống, đây là cách tôi giải quyết nó:
import fileinput
import sys
for line_number, line in enumerate(fileinput.input('file1.txt', inplace=1)):
if len(line) > 1:
sys.stdout.write(line)
Lưu ý: Các dòng trống trong trường hợp của tôi có độ dài 1
Nếu bạn sử dụng Linux, bạn có thể thử cách tiếp cận sau.
Giả sử bạn có một tệp văn bản có tên animal.txt
:
$ cat animal.txt
dog
pig
cat
monkey
elephant
Xóa dòng đầu tiên:
>>> import subprocess
>>> subprocess.call(['sed','-i','/.*dog.*/d','animal.txt'])
sau đó
$ cat animal.txt
pig
cat
monkey
elephant
Tôi nghĩ rằng nếu bạn đọc tệp vào một danh sách, thì hãy làm theo cách bạn có thể lặp qua danh sách để tìm tên hiệu bạn muốn loại bỏ. Bạn có thể làm điều đó hiệu quả mà không cần tạo thêm tệp, nhưng bạn sẽ phải ghi lại kết quả vào tệp nguồn.
Đây là cách tôi có thể làm điều này:
import, os, csv # and other imports you need
nicknames_to_delete = ['Nick', 'Stephen', 'Mark']
Tôi giả sử nicknames.csv
có chứa dữ liệu như:
Nick
Maria
James
Chris
Mario
Stephen
Isabella
Ahmed
Julia
Mark
...
Sau đó tải tập tin vào danh sách:
nicknames = None
with open("nicknames.csv") as sourceFile:
nicknames = sourceFile.read().splitlines()
Tiếp theo, lặp lại danh sách để khớp với đầu vào của bạn cần xóa:
for nick in nicknames_to_delete:
try:
if nick in nicknames:
nicknames.pop(nicknames.index(nick))
else:
print(nick + " is not found in the file")
except ValueError:
pass
Cuối cùng, viết kết quả trở lại vào tập tin:
with open("nicknames.csv", "a") as nicknamesFile:
nicknamesFile.seek(0)
nicknamesFile.truncate()
nicknamesWriter = csv.writer(nicknamesFile)
for name in nicknames:
nicknamesWriter.writeRow([str(name)])
nicknamesFile.close()
Nói chung, bạn không thể; bạn phải viết lại toàn bộ tập tin (ít nhất là từ điểm thay đổi đến cuối).
Trong một số trường hợp cụ thể, bạn có thể làm tốt hơn thế này -
nếu tất cả các thành phần dữ liệu của bạn có cùng độ dài và không theo thứ tự cụ thể và bạn biết phần bù của phần tử bạn muốn loại bỏ, bạn có thể sao chép mục cuối cùng qua mục cần xóa và cắt bớt tệp trước mục cuối cùng ;
hoặc bạn chỉ có thể ghi đè lên đoạn dữ liệu với 'đây là dữ liệu xấu, bỏ qua giá trị' hoặc giữ cờ 'mục này đã bị xóa' trong các thành phần dữ liệu đã lưu của bạn để bạn có thể đánh dấu nó bị xóa mà không cần sửa đổi tệp.
Đây có thể là quá mức cần thiết cho các tài liệu ngắn (bất cứ điều gì dưới 100 KB?).
Có lẽ, bạn đã có một câu trả lời đúng, nhưng đây là của tôi. Thay vì sử dụng danh sách để thu thập dữ liệu chưa được lọc ( readlines()
phương pháp nào), tôi sử dụng hai tệp. Một là để giữ dữ liệu chính và thứ hai là để lọc dữ liệu khi bạn xóa một chuỗi cụ thể. Đây là một mã:
main_file = open('data_base.txt').read() # your main dataBase file
filter_file = open('filter_base.txt', 'w')
filter_file.write(main_file)
filter_file.close()
main_file = open('data_base.txt', 'w')
for line in open('filter_base'):
if 'your data to delete' not in line: # remove a specific string
main_file.write(line) # put all strings back to your db except deleted
else: pass
main_file.close()
Hy vọng bạn sẽ tìm thấy điều này hữu ích! :)
Lưu các dòng tệp trong danh sách, sau đó xóa danh sách dòng bạn muốn xóa và ghi các dòng còn lại vào một tệp mới
with open("file_name.txt", "r") as f:
lines = f.readlines()
lines.remove("Line you want to delete\n")
with open("new_file.txt", "w") as new_f:
for line in lines:
new_f.write(line)
Dưới đây là một số phương pháp khác để xóa một / một số dòng khỏi tệp:
src_file = zzzz.txt
f = open(src_file, "r")
contents = f.readlines()
f.close()
contents.pop(idx) # remove the line item from list, by line number, starts from 0
f = open(src_file, "w")
contents = "".join(contents)
f.write(contents)
f.close()
Bạn có thể sử dụng
re
thư viện
Giả sử rằng bạn có thể tải tệp txt đầy đủ của mình. Sau đó, bạn xác định danh sách các biệt danh không mong muốn và sau đó thay thế chúng bằng một chuỗi trống "".
# Delete unwanted characters
import re
# Read, then decode for py2 compat.
path_to_file = 'data/nicknames.txt'
text = open(path_to_file, 'rb').read().decode(encoding='utf-8')
# Define unwanted nicknames and substitute them
unwanted_nickname_list = ['SourDough']
text = re.sub("|".join(unwanted_nickname_list), "", text)
Để xóa một dòng cụ thể của một tệp theo số dòng của nó :
Thay thế tên tệp và line_to_delete bằng tên tệp của bạn và số dòng bạn muốn xóa.
filename = 'foo.txt'
line_to_delete = 3
initial_line = 1
file_lines = {}
with open(filename) as f:
content = f.readlines()
for line in content:
file_lines[initial_line] = line.strip()
initial_line += 1
f = open(filename, "w")
for line_number, line_content in file_lines.items():
if line_number != line_to_delete:
f.write('{}\n'.format(line_content))
f.close()
print('Deleted line: {}'.format(line_to_delete))
Ví dụ đầu ra :
Deleted line: 3
for nb, line in enumerate(f.readlines())
Lấy nội dung của tệp, chia nó theo dòng mới thành một tuple. Sau đó, truy cập số dòng của tuple của bạn, tham gia bộ kết quả của bạn và ghi đè lên tệp.
tuple(f.read().split('\n'))
?? (2) "truy cập số dòng của tuple của bạn" và "tham gia tuple kết quả của bạn" nghe có vẻ khá bí ẩn; mã Python thực tế có thể dễ hiểu hơn.
fileinput
theo mô tả của @ jf-sebastian tại đây . Nó dường như cho phép bạn làm việc từng dòng một, thông qua một tệp tạm thời, tất cả chỉ với mộtfor
cú pháp đơn giản .