किसी फ़ाइल में टेक्स्ट को कैसे खोजें और बदलें?


212

मैं पायथन 3 का उपयोग करके किसी फ़ाइल में टेक्स्ट कैसे खोज और बदल सकता हूँ?

यहाँ मेरा कोड है:

import os
import sys
import fileinput

print ("Text to search for:")
textToSearch = input( "> " )

print ("Text to replace it with:")
textToReplace = input( "> " )

print ("File to perform Search-Replace on:")
fileToSearch  = input( "> " )
#fileToSearch = 'D:\dummy1.txt'

tempFile = open( fileToSearch, 'r+' )

for line in fileinput.input( fileToSearch ):
    if textToSearch in line :
        print('Match Found')
    else:
        print('Match Not Found!!')
    tempFile.write( line.replace( textToSearch, textToReplace ) )
tempFile.close()


input( '\n\n Press Enter to exit...' )

इनपुट फ़ाइल:

hi this is abcd hi this is abcd
This is dummy text file.
This is how search and replace works abcd

जब मैं उपरोक्त इनपुट फ़ाइल में 'abcd' द्वारा 'ram' को खोजता और प्रतिस्थापित करता हूँ, तो यह एक आकर्षण का काम करता है। लेकिन जब मैं इसे 'राम' द्वारा 'एब्सकांड' के स्थान पर उल्टा कर देता हूं, तो कुछ रद्दी पात्रों को छोड़ दिया जाता है।

'Abcd' को 'ram' से बदलना

hi this is ram hi this is ram
This is dummy text file.
This is how search and replace works rambcd

क्या आप कुछ अधिक विशिष्ट हो सकते हैं जब आप कहते हैं कि "कुछ जंक पात्रों को अंत में छोड़ दिया जाता है", आप क्या देखते हैं?
बुरहान खालिद

आउटपुट के साथ प्रश्न अपडेट करें जो मुझे मिला।
श्रीराम

जवाबों:


241

fileinputपहले से ही inplace edit का समर्थन करता है। यह stdoutइस मामले में फ़ाइल पर पुनर्निर्देशित करता है:

#!/usr/bin/env python3
import fileinput

with fileinput.FileInput(filename, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(text_to_search, replacement_text), end='')

13
end=''तर्क क्या करना चाहिए है?
egpbos

18
lineपहले से ही एक नई लाइन है। endडिफ़ॉल्ट रूप से एक नई end=''print()
रेखा है

11
Fileinput का उपयोग न करें! इसके बजाय खुद ऐसा करने के लिए कोड लिखने पर विचार करें। Sys.stdout को पुनर्निर्देशित करना एक महान विचार नहीं है, खासकर यदि आप इसे बिना किसी प्रयास के कर रहे हैं..तो जैसे फाइलइनपुट करता है। यदि कोई अपवाद उठाया जाता है, तो आपका स्टडआउट कभी बहाल नहीं हो सकता है।
14:09

9
@ क्रैड्स: गलत। fileinputके लिए एक उपकरण नहीं है सभी नौकरियों ( कुछ भी नहीं है), लेकिन लेकिन कई मामलों में यह कर रहे हैं है एक को लागू करने के सही उपकरण जैसे, sedपायथन में की तरह फिल्टर। नाखूनों को पाउंड करने के लिए एक पेचकश का उपयोग न करें।
JFS

5
यदि आप वास्तव में किसी कारण से अपनी फ़ाइल पर रीडायरेक्ट पुनर्निर्देशित करना चाहते हैं, तो इसे करने से बेहतर नहीं fileinputहै (मूल रूप से, उपयोग try..finallyया संदर्भकर्ता यह सुनिश्चित करने के लिए कि आप स्टडआउट को उसके बाद मूल मूल्य पर सेट करें)। के लिए स्रोत कोड fileinputबहुत आंखों से खून बह रहा है भयानक है, और यह हुड के तहत कुछ वास्तव में असुरक्षित चीजें करता है। अगर यह आज लिखा जाता है तो मुझे बहुत संदेह है कि इसने इसे stdlib में बनाया होगा।
22

333

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

# Read in the file
with open('file.txt', 'r') as file :
  filedata = file.read()

# Replace the target string
filedata = filedata.replace('ram', 'abcd')

# Write the file out again
with open('file.txt', 'w') as file:
  file.write(filedata)

जब तक कि आपके पास काम करने के लिए एक विशाल फ़ाइल नहीं है, जिसके साथ एक बार में मेमोरी में लोड करना बहुत बड़ा है, या आप संभावित डेटा हानि के बारे में चिंतित हैं यदि प्रक्रिया दूसरे चरण के दौरान बाधित होती है जिसमें आप फ़ाइल में डेटा लिखते हैं।


5
with file = open(..):पाइथन मान्य नहीं है ( =) हालांकि इरादा स्पष्ट है। .replace()स्ट्रिंग को संशोधित नहीं करता है (यह अपरिवर्तनीय है) ताकि आपको लौटे मूल्य का उपयोग करने की आवश्यकता हो। वैसे भी बड़ी फ़ाइलों का समर्थन करने वाला कोड तब तक और भी सरल हो सकता है जब तक कि आपको कई पंक्तियों में पाठ को खोजने और बदलने की आवश्यकता न हो।
jfs

40
आप काफी सही हैं, और यह कि - लोग - इसलिए आपको इंटरनेट पर खुद को शर्मिंदा करने से पहले अपने कोड का परीक्षण करना चाहिए;)
जैक एडले

19
@JonasStein: नहीं, यह नहीं होना चाहिए। withबयान स्वचालित रूप से बयान ब्लॉक के अंत में फ़ाइल बंद कर देता है।
जैक ऐडली

2
@JackAidley जो दिलचस्प है। विवरण के लिए आपका धन्यवाद।
जोनास स्टीन

4
@JackAidley क्योंकि यह छोटा, सरल, आसानी से उपयोग और समझा जाता है, और एक वास्तविक समस्या को संबोधित करता है जो बहुत सारे लोगों के पास है (और इसलिए कि बहुत सारे लोग खोजते हैं - इस प्रकार आपका उत्तर खोजते हैं)।
बेन बार्डन

52

जैसा कि जैक एडले ने पोस्ट किया था और जेएफ सेबेस्टियन ने बताया, यह कोड काम नहीं करेगा:

 # Read in the file
filedata = None
with file = open('file.txt', 'r') :
  filedata = file.read()

# Replace the target string
filedata.replace('ram', 'abcd')

# Write the file out again
with file = open('file.txt', 'w') :
  file.write(filedata)`

लेकिन यह कोड काम करेगा (मैंने इसका परीक्षण किया है):

f = open(filein,'r')
filedata = f.read()
f.close()

newdata = filedata.replace("old data","new data")

f = open(fileout,'w')
f.write(newdata)
f.close()

इस पद्धति का उपयोग करना, फाइलिन और फाइलआउट एक ही फाइल हो सकती है, क्योंकि पायथन 3.3 लिखने के लिए खुलने पर फाइल को ओवरराइट कर देगा।


9
मेरा मानना ​​है कि अंतर यहाँ है: filata.replace ('ram', 'abcd') की तुलना में: newdata = lodata.replace ("पुराना डेटा", "नया डेटा") "कथन" के साथ कुछ नहीं करना है
Diegomanas

5
1. क्यों हटाओ with-स्टेटमेंट? 2. जैसा कि मेरे उत्तर में कहा गया है, fileinputयह कार्यस्थल पर काम कर सकता है - यह डेटा को एक ही फाइल में बदल सकता है (यह एक अस्थायी फ़ाइल का आंतरिक रूप से उपयोग करता है)। अंतर यह है कि fileinputपूरी फ़ाइल को मेमोरी में लोड करने की आवश्यकता नहीं है।
jfs

8
बस जैक एडली के उत्तर को फिर से देखने के लिए दूसरों को बचाने के लिए, इस उत्तर के बाद से इसे ठीक कर दिया गया है, इसलिए यह अब बेमानी है (और नीटर withब्लॉक खोने के कारण अवर )।
क्रिस

46

आप इस तरह से प्रतिस्थापन कर सकते हैं

f1 = open('file1.txt', 'r')
f2 = open('file2.txt', 'w')
for line in f1:
    f2.write(line.replace('old_text', 'new_text'))
f1.close()
f2.close()

7

आप भी इस्तेमाल कर सकते हैं pathlib

from pathlib2 import Path
path = Path(file_to_search)
text = path.read_text()
text = text.replace(text_to_search, replacement_text)
path.write_text(text)

धन्यवाद युया। उपरोक्त समाधान ने अच्छी तरह से काम किया। नोट: आपको अपनी मूल फ़ाइल का बैकअप लेने की आवश्यकता है, क्योंकि यह आपकी मूल फ़ाइल को स्वयं बदल देता है। यदि आप पाठ को बार-बार बदलना चाहते हैं तो नीचे अंतिम 2 पंक्तियों को जोड़ सकते हैं। text = text.replace (text_to_search, प्रतिस्थापन_text) पाथ ।write_text (पाठ)
नाग्स

3

ब्लॉक वाले एकल के साथ, आप अपने पाठ को खोज और बदल सकते हैं:

with open('file.txt','r+') as f:
    filedata = f.read()
    filedata = filedata.replace('abc','xyz')
    f.truncate(0)
    f.write(filedata)

1
आप seekइसे लिखने से पहले फ़ाइल की शुरुआत में भूल गए । truncateऐसा नहीं करता है और इसलिए आपके पास फ़ाइल में कचरा होगा।
उर

2

आपकी समस्या एक ही फ़ाइल से पढ़ने और लिखने से उपजी है। fileToSearchलिखने के लिए खोलने के बजाय , एक वास्तविक अस्थायी फ़ाइल खोलें और फिर आपके द्वारा किए जाने और बंद होने के बाद tempFile, os.renameनई फ़ाइल को स्थानांतरित करने के लिए उपयोग करें fileToSearch


1
फ्रेंडली एफएफआई (जवाब में संपादित करने के लिए स्वतंत्र महसूस): मूल कारण जगह में एक फ़ाइल के मध्य को छोटा करने में सक्षम नहीं है। यही है, यदि आप 5 वर्णों को खोजते हैं और 3 से प्रतिस्थापित करते हैं, तो खोजे गए 5 में से पहले 3 वर्णों को बदल दिया जाएगा; लेकिन अन्य 2 को हटाया नहीं जा सकता, वे बस वहीं रहेंगे। अस्थायी फ़ाइल समाधान इन "बचे हुए" वर्णों को अस्थायी फ़ाइल से बाहर लिखने के बजाय उन्हें हटाकर हटा देता है।
michaelb958 - GoFundMonica

2

(पाइप स्थापित अजगर-उपयोग)

from pyutil import filereplace

filereplace("somefile.txt","abcd","ram")

दूसरा पैरामीटर (प्रतिस्थापित की जाने वाली चीज़, उदाहरण के लिए "abcd" भी एक regex हो सकता है)
सभी घटनाओं को प्रतिस्थापित करेगा


मुझे इसके साथ कुछ बुरा अनुभव था (इसने कुछ पात्रों को फ़ाइल के अंत में जोड़ा), इसलिए मैं इसकी सिफारिश नहीं कर सकता, भले ही एक-लाइनर अच्छा होगा।
अजरेल 3000

@ Azrael3000 इसमें वर्ण जोड़े गए? मैंने अपने साथ ऐसा नहीं देखा। मैं अत्यधिक अगर आप Github ony एक मुद्दा खोला तो मैं इसे ठीक कर सकते हैं की सराहना करेंगे github.com/MisterL2/python-util
MisterL2

1

मेरा संस्करण, पूरी फाइल पर एक समय में एक शब्द।

मैंने इसे स्मृति में पढ़ा।

def replace_word(infile,old_word,new_word):
    if not os.path.isfile(infile):
        print ("Error on replace_word, not a regular file: "+infile)
        sys.exit(1)

    f1=open(infile,'r').read()
    f2=open(infile,'w')
    m=f1.replace(old_word,new_word)
    f2.write(m)

0

मैंने यह कर दिया:

#!/usr/bin/env python3

import fileinput
import os

Dir = input ("Source directory: ")
os.chdir(Dir)

Filelist = os.listdir()
print('File list: ',Filelist)

NomeFile = input ("Insert file name: ")

CarOr = input ("Text to search: ")

CarNew = input ("New text: ")

with fileinput.FileInput(NomeFile, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(CarOr, CarNew), end='')

file.close ()

दु: खी है, लेकिन fileinput साथ नहीं doen काम inplace=Trueके साथ utf-8
सर्जियो

0

मैंने जयराम सिंह के पद को थोड़ा संशोधित किया ताकि 'हर' को बदल दिया जा सके। ' एक नंबर पर चरित्र जिसे मैं प्रत्येक उदाहरण के साथ बढ़ाना चाहता था। सोचा कि यह उस व्यक्ति के लिए सहायक हो सकता है जो एक ऐसे चरित्र को संशोधित करना चाहता था जो प्रति पंक्ति एक से अधिक बार घटित हुआ और पुनरावृति करना चाहता था। आशा है कि किसी की मदद करता है। PS- अगर मेरी पोस्ट किसी भी तरह से अनुचित है, तो मैं माफी माँगने के लिए बहुत नया हूँ, लेकिन मेरे लिए यह काम कर गया।

f1 = open('file1.txt', 'r')
f2 = open('file2.txt', 'w')
n = 1  

# if word=='!'replace w/ [n] & increment n; else append same word to     
# file2

for line in f1:
    for word in line:
        if word == '!':
            f2.write(word.replace('!', f'[{n}]'))
            n += 1
        else:
            f2.write(word)
f1.close()
f2.close()

0
def word_replace(filename,old,new):
    c=0
    with open(filename,'r+',encoding ='utf-8') as f:
        a=f.read()
        b=a.split()
        for i in range(0,len(b)):
            if b[i]==old:
                c=c+1
        old=old.center(len(old)+2)
        new=new.center(len(new)+2)
        d=a.replace(old,new,c)
        f.truncate(0)
        f.seek(0)
        f.write(d)
    print('All words have been replaced!!!')

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

0

इस तरह:

def find_and_replace(file, word, replacement):
  with open(file, 'r+') as f:
    text = f.read()
    f.write(text.replace(word, replacement))

कृपया सुनिश्चित करें कि इस प्रश्न में पहले से मौजूद अन्य उत्तरों पर आपका उत्तर बेहतर है।

यह फ़ाइल के अंत में प्रतिस्थापन के साथ पाठ को जोड़ देगा, मेरी राय में @ जेक ऐडली एसेवर सिर्फ ओपी का मतलब है stackoverflow.com/a/17141572/6875391
किरिल

-3
def findReplace(find, replace):

    import os 

    src = os.path.join(os.getcwd(), os.pardir) 

    for path, dirs, files in os.walk(os.path.abspath(src)):

        for name in files: 

            if name.endswith('.py'): 

                filepath = os.path.join(path, name)

                with open(filepath) as f: 

                    s = f.read()

                s = s.replace(find, replace) 

                with open(filepath, "w") as f:

                    f.write(s) 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.