파일에서 텍스트를 검색하고 바꾸는 방법?


212

Python 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

위의 입력 파일에서 'ram'을 'abcd'로 검색하고 바꾸면 매력으로 작동합니다. 그러나 그 반대로 할 때, 즉 'abcd'를 'ram'으로 바꾸면 일부 정크 문자가 끝납니다.

'ram'로 'abcd'교체

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

"일부 정크 문자가 남아있다"고 말할 때 좀 더 구체적으로 말할 수 있습니까?
Burhan Khalid 2016 년

내가 얻은 것을 출력으로 질문을 업데이트했습니다.
Shriram

답변:


241

fileinput내부 편집을 이미 지원합니다. 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()추가로 줄 바꿈을 인쇄하지 않는 기능
JFS

11
파일 입력을 사용하지 마십시오! 대신 직접 코드를 작성해보십시오. sys.stdout을 리디렉션하는 것은 좋은 생각이 아닙니다. 특히 fileinput과 마찬가지로 try..finally없이 수행하는 경우 특히 그렇습니다. 예외가 발생하면 stdout이 복원되지 않을 수 있습니다.
craigds

9
@ craigds : 잘못되었습니다. fileinput모든 작업을 위한 도구는 아니지만 ( 아무 것도 아님) , 파이썬에서 비슷한 필터 를 구현하는 등의 올바른 도구 되는 경우가 많습니다 sed. 손톱을 두드리기 위해 드라이버를 사용하지 마십시오.
jfs

5
어떤 이유로 든 stdout을 파일로 리디렉션 하려면 실제로 보다 나은 방법을 사용하는 것이 어렵지 fileinput않습니다 (기본적으로 try..finallystdout을 원래 값으로 다시 설정하도록 컨텍스트 관리자를 사용 하거나 컨텍스트 관리자를 사용하십시오). 의 소스 코드 fileinput는 눈에 띄게 끔찍하며, 실제로는 안전하지 않은 것들을 수행합니다. 오늘 쓰여졌다면 stdlib로 만들었을 것입니다.
craigds

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
당신은 꽤 옳습니다. 여러분 – 인터넷에서 자신을 당황시키기 전에 코드를 테스트해야하는 이유입니다.)
Jack Aidley

19
@JonasStein : 아뇨. with문은 자동으로 문 블록의 끝 부분에있는 파일을 닫습니다.
Jack Aidley

2
@JackAidley가 흥미 롭습니다. 설명 주셔서 감사합니다.
Jonas Stein

4
@JackAidley는 짧고 단순하며 쉽게 사용하고 이해하기 때문에 많은 사람들이 가지고있는 실제 문제를 해결하므로 많은 사람들이 검색하여 답을 찾습니다.
벤 Barden

52

Jack Aidley가 게시하고 JF Sebastian이 지적 했듯이이 코드는 작동하지 않습니다.

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

이 방법을 사용하면 filein과 fileout은 같은 파일 일 수 있습니다. Python 3.3은 파일을 열 때 파일을 덮어 쓰기 때문입니다.


9
차이점은 여기에 있습니다. filedata.replace ( 'ram', 'abcd') 다음과 비교 : newdata = filedata.replace ( "old data", "new data") "with"문과 관련이 없음
Diegomanas

5
1. 왜 with진술 을 제거 하시겠습니까? 2. 내 대답에서 언급했듯이 fileinput제자리에서 작동 할 수 있습니다-동일한 파일의 데이터를 대체 할 수 있습니다 (내부 임시 파일을 사용합니다). 차이점은 fileinput전체 파일을 메모리에로드 할 필요가 없다는 것입니다.
jfs

8
Jack Aidley의 답변을 재 방문하는 다른 사람들을 구하기 위해이 답변 이후 수정되었습니다. 이것은 이제 중복됩니다 (그리고 더 깔끔한 with블록 을 잃기 때문에 열등 합니다).
Chris

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)

고마워요 위의 솔루션은 잘 작동했습니다. 참고 : 원본 파일은 원본 파일을 대체하므로 원본 파일을 먼저 백업해야합니다. 텍스트를 반복해서 바꾸려면 아래 두 줄을 계속 추가하면됩니다. text = text.replace (text_to_search, replacement_text) path.write_text (text)
Nages

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그렇게하지 않으므로 파일에 쓰레기가 생깁니다.
ur.

2

문제는 동일한 파일을 읽고 쓰는 것에서 비롯됩니다. 오히려 개방보다 fileToSearch쓰기, 실제 임시 파일을 열고 작업을 완료하고 닫은 후 다음 tempFile, 사용 os.rename을 통해 새 파일을 이동합니다 fileToSearch.


1
친근한 참고 (답변으로 자유롭게 편집 할 수 있음) : 근본 원인이 파일 중간을 단축 할 수 없습니다. 즉, 5자를 검색하고 3으로 바꾸면 검색된 5의 처음 3자가 바뀝니다. 다른 2 개는 제거 할 수 없습니다. 임시 파일 솔루션은 이러한 "남은"문자를 임시 파일에 쓰지 않고 삭제하여 제거합니다.
michaelb958--GoFundMonica 2016 년

2

(pip install python-util)

from pyutil import filereplace

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

두 번째 매개 변수 (예 : "abcd"와 같이 대체되는 것은 정규식 일 수 있음)
모든 발생을 대체합니다.


나는 이것에 대한 나쁜 경험 (파일 끝에 문자를 추가했다)을 가지고 있었으므로 한 줄짜리가 좋더라도 추천 할 수는 없다.
Azrael3000

@ Azrael3000 문자를 추가 했습니까? 나는 그것이 나에게 일어나는 것을 보지 못했습니다. Github에서 문제를 열면 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.
Sergio

0

나는 '!'의 모든 인스턴스를 대체하기 위해 Jayram Singh의 게시물을 약간 수정했습니다. 문자를 각 인스턴스마다 증가시키고 자하는 숫자로 바꿉니다. 한 줄에 두 번 이상 발생한 문자를 수정하고 반복하려는 사람에게 도움이 될 수 있다고 생각했습니다. 누군가에게 도움이되기를 바랍니다. 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!!!')

이 코드는 원하는 단어를 대체합니다. 유일한 문제는 전체 파일을 다시 작성한다는 것입니다. 프로세서가 처리하기에 파일이 너무 길면 중단 될 수 있습니다.
Vinit Pillai

0

이렇게 :

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

이 질문에 이미 존재하는 다른 답변에 대한 답변이 향상되도록하십시오.
hongsy

@Jack Aidley aswer는 OP가 의미하는 것입니다 stackoverflow.com/a/17141572/6875391
Kirill

-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) 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.