Quero fazer um loop sobre o conteúdo de um arquivo de texto, fazer uma pesquisa e substituir em algumas linhas e escrever o resultado novamente no arquivo. Eu poderia primeiro carregar o arquivo inteiro na memória e depois escrevê-lo novamente, mas essa provavelmente não é a melhor maneira de fazê-lo.
Qual é a melhor maneira de fazer isso, dentro do código a seguir?
f = open(file)
for line in f:
if line.contains('foo'):
newline = line.replace('foo', 'bar')
# how to write this newline back to the file
file
está sombreando uma classe predefinida com o mesmo nome.mkstemp()
está retornando uma tupla de 2 e(fh, abs_path) = fh, abs_path
, eu não sabia disso quando fiz a pergunta.A maneira mais curta provavelmente seria usar o módulo fileinput . Por exemplo, o seguinte adiciona números de linha a um arquivo no local:
O que acontece aqui é:
print
instrução grava de volta no arquivo originalfileinput
tem mais sinos e assobios. Por exemplo, ele pode ser usado para operar automaticamente todos os arquivossys.args[1:]
, sem que você precise iterar explicitamente sobre eles. A partir do Python 3.2, ele também fornece um gerenciador de contexto conveniente para uso em umawith
instrução.Enquanto
fileinput
seja ótimo para scripts descartáveis, eu seria cauteloso em usá-lo em código real, porque é certo que não é muito legível ou familiar. No código real (de produção), vale a pena gastar apenas mais algumas linhas de código para tornar o processo explícito e, assim, tornar o código legível.Existem duas opções:
fonte
print(line, end='')
Aqui está outro exemplo que foi testado e corresponderá aos padrões de pesquisa e substituição:
Exemplo de uso:
fonte
searchExp in line
nãoline.replace
são operações de expressão regular. Certamente o exemplo de uso está errado.if searchExp in line: line = line.replace(searchExp, replaceExpr)
você pode apenas escreverline = line.replace(searchExp, replaceExpr)
. Nenhuma exceção é gerada, a linha permanece inalterada.sys.stdout.write(line)
. Obrigado novamente!Isso deve funcionar: (edição no local)
fonte
files
deve ser uma sequência que contém o nome do arquivo, não um objeto de arquivo .Com base na resposta de Thomas Watnedal. No entanto, isso não responde exatamente à parte linha a linha da pergunta original. A função ainda pode substituir linha a linha
Esta implementação substitui o conteúdo do arquivo sem usar arquivos temporários, como conseqüência, as permissões do arquivo permanecem inalteradas.
Também re.sub, em vez de substituir, permite a substituição de regex em vez de apenas substituição de texto sem formatação.
A leitura do arquivo como uma única sequência de caracteres, em vez de linha por linha, permite a correspondência e substituição de várias linhas.
fonte
rb
ewb
atribui ao abrir arquivos, pois isso irá preservar finais de linha originaisComo sugere o lassevk, escreva o novo arquivo à medida que avança, aqui está um exemplo de código:
fonte
Se você deseja uma função genérica que substitua qualquer texto por outro, provavelmente é o melhor caminho a seguir, principalmente se você é fã do regex:
fonte
Uma maneira mais pitônica seria usar gerenciadores de contexto como o código abaixo:
Você pode encontrar o snippet completo aqui .
fonte
Crie um novo arquivo, copie as linhas do antigo para o novo e faça a substituição antes de gravar as linhas no novo arquivo.
fonte
Expandindo a resposta de @ Kiran, que eu concordo é mais sucinta e Pythonic, isso adiciona codecs para apoiar a leitura e gravação de UTF-8:
fonte
Usando a resposta de hamishmcn como modelo, fui capaz de procurar uma linha em um arquivo que corresponda ao meu regex e substituí-lo por uma string vazia.
fonte
fileinput
é bastante direto, como mencionado nas respostas anteriores:Explicação:
fileinput
pode aceitar vários arquivos, mas prefiro fechar cada arquivo assim que estiver sendo processado. Então, colocado únicofile_path
nawith
declaração.print
A instrução não imprime nada quandoinplace=True
, porqueSTDOUT
está sendo encaminhada para o arquivo original.end=''
naprint
declaração é eliminar novas linhas intermediárias em branco.Pode ser usado da seguinte maneira:
fonte
se você remover o recuo como abaixo, ele pesquisará e substituirá em várias linhas. Veja abaixo, por exemplo.
fonte