किसी फ़ाइल में किसी विशिष्ट लाइन को हटाने के लिए पायथन का उपयोग करना


145

मान लीजिए कि मेरे पास उपनामों से भरी एक पाठ फ़ाइल है। मैं पायथन का उपयोग करके इस फ़ाइल से एक विशिष्ट उपनाम कैसे हटा सकता हूं?


1
प्रयास करें fileinputके रूप में @ जेएफ-सेबस्टियन द्वारा वर्णित यहाँ । यह आपको एक साधारण forसिंटैक्स के साथ, अस्थायी फ़ाइल के माध्यम से लाइन-बाय-लाइन काम करने की अनुमति देता है ।
केविन

जवाबों:


205

सबसे पहले, फ़ाइल खोलें और फ़ाइल से अपनी सभी लाइनें प्राप्त करें। फिर फ़ाइल को राइट मोड में फिर से खोलें और अपनी लाइनों को वापस लिखें, उस लाइन को छोड़कर, जिसे आप हटाना चाहते हैं:

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")तुलना में newline वर्ण की आवश्यकता है क्योंकि यदि आपकी फ़ाइल किसी newline वर्ण के साथ समाप्त lineनहीं होती है तो बहुत अंतिम नहीं होगी।


2
हमें इसे दो बार क्यों खोलना और बंद करना है?
ओकर

3
@ विकल्प: आपको फ़ाइल को दो बार खोलना होगा (और इसे बीच में बंद करना होगा) क्योंकि पहले मोड में यह "रीड-ओनली" है क्योंकि आप फ़ाइल में केवल वर्तमान लाइनों में पढ़ रहे हैं। फिर आप इसे बंद करते हैं और इसे "राइट मोड" में फिर से खोलते हैं, जहां फ़ाइल लिखने योग्य है और आप उस फ़ाइल की सामग्री को प्रतिस्थापित करते हैं जिसे आप निकालना चाहते थे।
डेविन

4
पायथन हमें एक पंक्ति में ऐसा करने की अनुमति क्यों नहीं देता है?
जोकर

5
@ जोकर, जब आप एक पंक्ति पढ़ते हैं, तो पंक्ति के साथ-साथ चलते हुए एक कर्सर की कल्पना करने की कोशिश करें। एक बार उस लाइन को पढ़ लिया गया है जिसे कर्सर अब अतीत में ले गया है। जब आप फ़ाइल में लिखने की कोशिश करते हैं तो आप लिखते हैं कि वर्तमान में कर्सर कहाँ है। फ़ाइल को फिर से खोलकर आप कर्सर को रीसेट करते हैं।
वद्दास

4
यौगिक के साथ प्रयोग करें!
स्केलुसवे सेप

100

इस समस्या का हल केवल एक खुले के साथ:

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-पॉइंटर को रीसेट करने के लिए खोज का उपयोग करता है।


2
यह मेरे लिए बहुत अच्छा काम करता था, क्योंकि मुझे लॉकफाइल का भी उपयोग करना था (fcntl)। मैं fcntl के साथ मिलकर fileinput का उपयोग करने का कोई भी तरीका नहीं ढूंढ सका।
इस्प्राइनिडर

1
इस समाधान के कुछ दुष्प्रभावों को देखना अच्छा होगा।
user1767754

3
मैं ऐसा नहीं करूंगा। यदि आपको forलूप में कोई त्रुटि मिलती है , तो आप आंशिक रूप से अधिलेखित फ़ाइल के साथ डुप्लिकेट लाइनों या एक लाइन को आधा काट देंगे। आप इसके बजाय f.truncate()सही करना चाह सकते हैं f.seek(0)। इस तरह अगर आपको कोई त्रुटि मिलती है तो आप एक अधूरी फ़ाइल के साथ समाप्त हो जाएंगे। लेकिन असली समाधान (यदि आपके पास डिस्क स्थान है) एक अस्थायी फ़ाइल के लिए आउटपुट है और तब सब कुछ सफल होने के बाद मूल के साथ इसका उपयोग os.replace()या pathlib.Path(temp_filename).replace(original_filename)स्वैप करना है।
बोरिस

हो सकता है कि आप i.strip('\n') != "line you want to remove..."स्वीकार किए गए उत्तर में वर्णित हैं, जो पूरी तरह से मेरी समस्या को हल करेगा। क्योंकि iमेरे लिए कुछ भी नहीं किया
Mangohero1

31

किसी सूची में सब कुछ संग्रहीत करने और इसे लिखने के लिए फ़ाइल को फिर से खोलने के बजाय सबसे अच्छा और सबसे तेज़ विकल्प, फ़ाइल को कहीं और फिर से लिखने के लिए मेरी राय में है।

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")
shrishinde

4
@ShriShinde जब आप फ़ाइल ऑब्जेक्ट पर लूपिंग करते हैं, तो आप फ़ाइल को मेमोरी में नहीं पढ़ रहे हैं, इसलिए यह समाधान आपके सुझाव के समान काम करता है।
स्टाइनर लीमा

आप मूल फ़ाइल को हटाना चाहते हैं और दूसरी फ़ाइल का नाम बदलकर मूल फ़ाइल का नाम रख सकते हैं, जो कि Linux OS पर पायथन के साथ दिखाई देगी,subprocess.call(['mv', 'newfile.txt', 'yourfile.txt'])
Max

6
os.replace(python v 3.3 में नया) सिस्टम कॉल टू से अधिक क्रॉस-प्लेटफॉर्म है mv
7yl4r

सरल और महान।
जुबैर ईस्वी सन्

27

यह @ लोर के उत्तर से एक "कांटा" है (जो मेरा मानना ​​है कि इसे सही उत्तर माना जाना चाहिए)।


इस तरह एक फ़ाइल के लिए:

$ 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मूल्यांकन के लिए और अधिक स्पष्ट अगर स्ट्रिंग वर्तमान लाइन में मौजूद नहीं है

यदि f.seek (0) की आवश्यकता है?
1

@ यिफान हां। अन्यथा फ़ाइल को अधिलेखित करने के बजाय आप फ़ाइल को अपने आप जोड़ देंगे (उन रेखाओं के बिना जिन्हें आप बाहर कर रहे हैं)।
बोरिस

5

पहली पास में लाइनों को पढ़ने और दूसरे पास में परिवर्तन (विशिष्ट लाइनों को हटाने) के साथ समस्या यह है कि यदि आप फ़ाइल का आकार बड़ा है, तो आप रैम से बाहर निकल जाएंगे। इसके बजाय, एक बेहतर तरीका यह है कि लाइनों को एक-एक करके पढ़ा जाए, और उन्हें एक अलग फाइल में लिखें, जिन्हें आपको ज़रूरत नहीं है। मैंने इस दृष्टिकोण को फ़ाइलों के साथ 12-50 GB तक चलाया है, और RAM उपयोग लगभग स्थिर है। केवल CPU चक्र प्रगति में प्रसंस्करण दिखाते हैं।


2

मुझे इस उत्तर में बताया गया फाइलइनपुट दृष्टिकोण पसंद आया: टेक्स्ट फाइल (अजगर) से एक लाइन हटाना

उदाहरण के लिए कहें कि मेरे पास एक फाइल है, जिसमें खाली लाइनें हैं और मैं खाली लाइनों को हटाना चाहता हूं, यहां बताया गया है कि मैंने इसे कैसे हल किया:

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 थी


2

यदि आप लिनक्स का उपयोग करते हैं, तो आप निम्नलिखित दृष्टिकोण की कोशिश कर सकते हैं।
मान लीजिए कि आपके पास एक टेक्स्ट फ़ाइल है जिसका नाम है 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

7
यह समाधान OS अज्ञेयवादी नहीं है, और चूंकि ओपी ने एक ऑपरेशन सिस्टम निर्दिष्ट नहीं किया है, इसलिए लिनक्स विशिष्ट उत्तर imo पोस्ट करने का कोई कारण नहीं है।
स्टाइनर लीमा

2
किसी को भी जो सिर्फ अजगर के साथ किया जा सकता है के लिए सबप्रोसेस का उपयोग करने का सुझाव देता है, एक डाउनवोट हो जाता है! और +1 से @SteinarLima ... मैं सहमत हूं
जेमी लिंडसे

2

मुझे लगता है कि यदि आप फ़ाइल को एक सूची में पढ़ते हैं, तो क्या आप उस सूची पर पुनरावृत्ति कर सकते हैं जिस उपनाम से आप छुटकारा चाहते हैं। आप अतिरिक्त फ़ाइलों को बनाए बिना इसे बहुत कुशलता से कर सकते हैं, लेकिन आपको परिणाम को स्रोत फ़ाइल पर लिखना होगा।

यहां बताया गया है कि मैं ऐसा कैसे कर सकता हूं:

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()

1

सामान्य तौर पर, आप नहीं कर सकते; आपको पूरी फाइल को फिर से लिखना होगा (कम से कम परिवर्तन के बिंदु से अंत तक)।

कुछ विशिष्ट मामलों में आप इससे बेहतर कर सकते हैं -

यदि आपके सभी डेटा तत्व समान लंबाई के हैं और किसी विशिष्ट क्रम में नहीं हैं, और आप जिस से छुटकारा पाना चाहते हैं, उसकी भरपाई जानते हैं, तो आप डिलीट की जाने वाली अंतिम वस्तु को कॉपी कर सकते हैं और अंतिम आइटम से पहले फ़ाइल को अलग कर सकते हैं ;

या आप 'यह खराब डेटा है, इसे छोड़ें' मान के साथ डेटा चंक को अधिलेखित कर सकते हैं या अपने सहेजे गए डेटा तत्वों में 'इस आइटम को हटा दिया गया है' ध्वज को ऐसे रख सकते हैं जैसे कि आप फ़ाइल को संशोधित किए बिना इसे हटाए बिना चिह्नित कर सकते हैं।

यह शायद छोटे दस्तावेजों (100 KB के तहत कुछ भी?) के लिए ओवरकिल है।


1

शायद, आपको पहले से ही एक सही उत्तर मिल गया है, लेकिन यहां मेरा है। अनफ़िल्टर्ड डेटा (क्या 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()

आशा है आपको यह उपयोगी लगेगा! :)


0

किसी सूची में फ़ाइल लाइनों को सहेजें, फिर उस सूची को हटा दें जिसे आप हटाना चाहते हैं और एक नई फ़ाइल के लिए शेष लाइनें लिखें

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)

उत्तर देते समय कुछ स्पष्टीकरण देना बेहतर होता है क्योंकि आपका उत्तर एक है।
स्टीफन राउच

यदि आपकी फ़ाइल किसी नई पंक्ति के साथ समाप्त नहीं होती है, तो यह कोड अंतिम पंक्ति को नहीं हटाएगा, भले ही इसमें वह शब्द हो जिसे आप निकालना चाहते हैं।
बोरिस

0

एक फ़ाइल से / कुछ लाइन निकालने के लिए यहाँ कुछ अन्य विधि है:

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()

0

मुझे फाइलइनपुट और 'इनप्ले' विधि का उपयोग करना पसंद है:

import fileinput
for line in fileinput.input(fname, inplace =1):
    line = line.strip()
    if not 'UnwantedWord' in line:
        print(line)

यह अन्य उत्तरों की तुलना में थोड़ा कम चिंताजनक है और इसके लिए काफी तेज है


0

आप reपुस्तकालय का उपयोग कर सकते हैं

यह मानते हुए कि आप अपनी पूरी txt-file को लोड करने में सक्षम हैं। आप तब अवांछित उपनामों की एक सूची को परिभाषित करते हैं और फिर उन्हें एक रिक्त स्ट्रिंग "" के साथ प्रतिस्थापित करते हैं।

# 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)

-1

किसी फ़ाइल की विशिष्ट पंक्ति को उसकी पंक्ति संख्या द्वारा हटाने के लिए :

अपनी फ़ाइल का नाम और वह लाइन नंबर जिसे आप हटाना चाहते हैं, के साथ वैरिएबल फ़ाइल नाम और 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())
डायोनिस

-3

फ़ाइल की सामग्री को लें, इसे न्यूलाइन द्वारा एक टपल में विभाजित करें। फिर, अपने tuple के लाइन नंबर पर पहुँचें, अपना परिणाम tuple मिलाएँ, और फ़ाइल पर अधिलेखित करें।


6
(१) क्या आपका मतलब है tuple(f.read().split('\n'))?? (2) "अपने ट्यूपल लाइन नंबर तक पहुंचें" और "अपने परिणाम में शामिल हों" ध्वनि बल्कि रहस्यमय; वास्तविक पायथन कोड अधिक समझने योग्य हो सकता है।
जॉन माकिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.