สมมติว่าฉันมีไฟล์ข้อความที่เต็มไปด้วยชื่อเล่น ฉันจะลบชื่อเล่นเฉพาะจากไฟล์นี้โดยใช้ Python ได้อย่างไร
สมมติว่าฉันมีไฟล์ข้อความที่เต็มไปด้วยชื่อเล่น ฉันจะลบชื่อเล่นเฉพาะจากไฟล์นี้โดยใช้ Python ได้อย่างไร
คำตอบ:
ก่อนอื่นให้เปิดไฟล์และรับทุกบรรทัดของคุณจากไฟล์ จากนั้นเปิดไฟล์อีกครั้งในโหมดเขียนและเขียนบรรทัดของคุณกลับยกเว้นบรรทัดที่คุณต้องการลบ:
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)
คุณต้องstrip("\n")
ใช้อักขระขึ้นบรรทัดใหม่ในการเปรียบเทียบเพราะหากไฟล์ของคุณไม่ลงท้ายด้วยอักขระขึ้นบรรทัดใหม่ตัวสุดท้ายline
จะไม่เหมือนกัน
วิธีแก้ไขปัญหานี้โดยเปิดเพียงครั้งเดียว:
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()
วิธีการแก้ปัญหานี้จะเปิดไฟล์ในโหมด r / w ("r +") และใช้การค้นหาเพื่อรีเซ็ตตัวชี้ f จากนั้นตัดปลายเพื่อลบทุกอย่างหลังจากการเขียนครั้งล่าสุด
for
ลูปคุณจะพบไฟล์ที่ถูกเขียนทับบางส่วนโดยมีบรรทัดที่ซ้ำกันหรือตัดครึ่งบรรทัด คุณอาจต้องการf.truncate()
หลังจากf.seek(0)
แทน ด้วยวิธีนี้หากคุณได้รับข้อผิดพลาดคุณจะจบลงด้วยไฟล์ที่ไม่สมบูรณ์ แต่ทางออกที่แท้จริง (ถ้าคุณมีพื้นที่ว่างในดิสก์) คือการส่งออกไปยังไฟล์ชั่วคราวจากนั้นใช้os.replace()
หรือpathlib.Path(temp_filename).replace(original_filename)
เพื่อสลับกับต้นฉบับหลังจากทุกอย่างสำเร็จ
i.strip('\n') != "line you want to remove..."
ดังกล่าวในคำตอบที่ยอมรับว่าจะแก้ปัญหาของฉันอย่างสมบูรณ์ เพราะi
ไม่ได้ทำอะไรเพื่อฉันเลย
ตัวเลือกที่ดีที่สุดและเร็วที่สุดแทนที่จะเก็บทุกอย่างไว้ในรายการและเปิดไฟล์ใหม่เพื่อเขียนมันเป็นความคิดของฉันที่จะเขียนไฟล์ใหม่ที่อื่น
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)
แค่นั้นแหละ! ในวงเดียวและวงเดียวคุณก็สามารถทำสิ่งเดียวกันได้ มันจะเร็วขึ้นมาก
(output.write(line) for line in input if line!="nickname_to_delete"+"\n")
subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
os.replace
(ใหม่ในหลาม V 3.3) mv
มีมากขึ้นข้ามแพลตฟอร์มกว่าการโทรระบบ
นี่คือ "ทางแยก" จากคำตอบของ@Lother (ซึ่งฉันเชื่อว่าควรเป็นคำตอบที่ถูกต้อง)
สำหรับไฟล์เช่นนี้:
$ cat file.txt
1: october rust
2: november rain
3: december snow
ทางแยกจากโซลูชันของ Lother นี้ใช้ได้ผลดี:
#!/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()
การปรับปรุง:
with open
ซึ่งยกเลิกการใช้งานของ f.close()
if/else
สำหรับการประเมินว่าสตริงไม่ได้อยู่ในบรรทัดปัจจุบันปัญหาเกี่ยวกับการอ่านบรรทัดในการผ่านครั้งแรกและการเปลี่ยนแปลง (การลบบรรทัดที่ระบุ) ในรอบที่สองคือถ้าคุณขนาดไฟล์มีขนาดใหญ่คุณจะหมด RAM วิธีที่ดีกว่าคือการอ่านบรรทัดทีละบรรทัดแล้วเขียนลงในไฟล์แยกต่างหากกำจัดสิ่งที่คุณไม่ต้องการ ฉันใช้วิธีการนี้กับไฟล์ที่มีขนาดใหญ่ถึง 12-50 GB และการใช้ RAM ยังคงไม่เปลี่ยนแปลง รอบการทำงานของ CPU เท่านั้นที่แสดงการดำเนินการ
ฉันชอบวิธีป้อนไฟล์ตามที่อธิบายในคำตอบนี้: การ ลบบรรทัดออกจากไฟล์ข้อความ (ไพ ธ อน)
พูดเช่นฉันมีไฟล์ที่มีบรรทัดว่างอยู่ในนั้นและฉันต้องการลบบรรทัดว่างนี่คือวิธีที่ฉันแก้ไขมัน:
import fileinput
import sys
for line_number, line in enumerate(fileinput.input('file1.txt', inplace=1)):
if len(line) > 1:
sys.stdout.write(line)
หมายเหตุ: บรรทัดว่างในกรณีของฉันมีความยาว 1
หากคุณใช้ Linux คุณสามารถลองวิธีการต่อไปนี้
สมมติว่าคุณมีไฟล์ข้อความชื่อanimal.txt
:
$ cat animal.txt
dog
pig
cat
monkey
elephant
ลบบรรทัดแรก:
>>> import subprocess
>>> subprocess.call(['sed','-i','/.*dog.*/d','animal.txt'])
แล้วก็
$ cat animal.txt
pig
cat
monkey
elephant
ฉันคิดว่าถ้าคุณอ่านไฟล์ลงในรายการคุณสามารถทำซ้ำในรายการเพื่อค้นหาชื่อเล่นที่คุณต้องการกำจัด คุณสามารถทำได้อย่างมีประสิทธิภาพโดยไม่ต้องสร้างไฟล์เพิ่มเติม แต่คุณจะต้องเขียนผลลัพธ์กลับไปที่ไฟล์ต้นฉบับ
นี่คือวิธีที่ฉันอาจทำสิ่งนี้:
import, os, csv # and other imports you need
nicknames_to_delete = ['Nick', 'Stephen', 'Mark']
ฉันสมมติว่าnicknames.csv
มีข้อมูลเช่น:
Nick
Maria
James
Chris
Mario
Stephen
Isabella
Ahmed
Julia
Mark
...
จากนั้นโหลดไฟล์ลงในรายการ:
nicknames = None
with open("nicknames.csv") as sourceFile:
nicknames = sourceFile.read().splitlines()
ถัดไปทำซ้ำในรายการเพื่อจับคู่อินพุตของคุณเพื่อลบ:
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
สุดท้ายเขียนผลลัพธ์กลับไปเป็นไฟล์:
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()
โดยทั่วไปแล้วคุณไม่สามารถ; คุณต้องเขียนไฟล์ทั้งหมดอีกครั้ง (อย่างน้อยจากจุดเปลี่ยนไปยังจุดสิ้นสุด)
ในบางกรณีคุณสามารถทำได้ดีกว่านี้ -
หากองค์ประกอบข้อมูลทั้งหมดของคุณมีความยาวเท่ากันและไม่มีคำสั่งซื้อที่เฉพาะเจาะจงและคุณรู้ว่าออฟเซ็ตของสิ่งที่คุณต้องการกำจัดคุณสามารถคัดลอกรายการสุดท้ายเหนือรายการที่จะถูกลบและตัดทอนไฟล์ก่อนรายการสุดท้าย ;
หรือคุณสามารถเขียนทับกลุ่มข้อมูลด้วยค่า 'นี่คือข้อมูลที่ไม่ดีข้ามมัน' หรือเก็บค่าสถานะ 'รายการนี้ถูกลบ' ในองค์ประกอบข้อมูลที่บันทึกไว้ของคุณเพื่อให้คุณสามารถทำเครื่องหมายว่าถูกลบโดยไม่ต้องแก้ไขไฟล์
อาจเป็นเพราะเอกสารสั้นเกินไป (มีขนาดต่ำกว่า 100 KB)
อาจเป็นไปได้ว่าคุณได้รับคำตอบที่ถูกต้อง แต่นี่คือของฉัน แทนที่จะใช้รายการเพื่อรวบรวมข้อมูลที่ไม่มีการกรอง ( readlines()
วิธีใดบ้าง) ฉันใช้สองไฟล์ อันที่หนึ่งใช้สำหรับเก็บข้อมูลหลักและข้อที่สองใช้สำหรับการกรองข้อมูลเมื่อคุณลบสตริงที่ระบุ นี่คือรหัส:
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()
หวังว่าคุณจะพบว่ามีประโยชน์นี้! :)
บันทึกบรรทัดไฟล์ในรายการจากนั้นลบรายการบรรทัดที่คุณต้องการลบและเขียนบรรทัดที่เหลือลงในไฟล์ใหม่
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)
นี่คือวิธีอื่นในการลบ / บางบรรทัดออกจากไฟล์:
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()
ฉันชอบวิธีนี้ใช้ fileinput และวิธีการ 'inplace':
import fileinput
for line in fileinput.input(fname, inplace =1):
line = line.strip()
if not 'UnwantedWord' in line:
print(line)
มันพูดน้อยกว่าคำตอบอื่น ๆ เล็กน้อยและเร็วพอสำหรับ
คุณสามารถใช้
re
ห้องสมุด
สมมติว่าคุณสามารถโหลดไฟล์ txt เต็มของคุณได้ จากนั้นคุณจะกำหนดรายการชื่อเล่นที่ไม่ต้องการแล้วแทนที่ด้วยสตริงว่าง ""
# 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)
หากต้องการลบบรรทัดของไฟล์ด้วยหมายเลขบรรทัด :
แทนที่ชื่อไฟล์ตัวแปรและline_to_deleteด้วยชื่อไฟล์ของคุณและหมายเลขบรรทัดที่คุณต้องการลบ
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))
ตัวอย่างผลลัพธ์ :
Deleted line: 3
for nb, line in enumerate(f.readlines())
นำเนื้อหาของไฟล์แยกโดยการขึ้นบรรทัดใหม่เป็น tuple จากนั้นเข้าถึงหมายเลขบรรทัดของ tuple ของคุณเข้าร่วม tuple ผลลัพธ์ของคุณและเขียนทับลงในไฟล์
tuple(f.read().split('\n'))
?? (2) "เข้าถึงหมายเลขบรรทัดของ tuple" และ "เข้าร่วม tuple ผลลัพธ์ของคุณ" เสียงค่อนข้างลึกลับ รหัส Python จริงอาจเข้าใจได้มากกว่า
fileinput
ตามที่อธิบาย @ JF-เซบาสเตียนที่นี่ ดูเหมือนว่าจะช่วยให้คุณทำงานแบบบรรทัดต่อบรรทัดผ่านไฟล์ชั่วคราวทั้งหมดด้วยfor
ไวยากรณ์อย่างง่าย