Reemplazar cadenas en archivos por Python

¿Cómo puede reemplazar la coincidencia con el reemplazo dado recursivamente en un directorio dado y sus subdirectorios?

Pseudocódigo

import os import re from os.path import walk for root, dirs, files in os.walk("/home/noa/Desktop/codes"): for name in dirs: re.search("dbname=noa user=noa", "dbname=masi user=masi") // I am trying to replace here a given match in a file 

Related of "Reemplazar cadenas en archivos por Python"

Coloque todo este código en un archivo llamado mass_replace . Bajo Linux o Mac OS X, puede hacer chmod +x mass_replace y luego ejecutar esto. Bajo Windows, puedes ejecutarlo con python mass_replace seguido de los argumentos apropiados.

 #!/usr/bin/python import os import re import sys # list of extensions to replace DEFAULT_REPLACE_EXTENSIONS = None # example: uncomment next line to only replace *.c, *.h, and/or *.txt # DEFAULT_REPLACE_EXTENSIONS = (".c", ".h", ".txt") def try_to_replace(fname, replace_extensions=DEFAULT_REPLACE_EXTENSIONS): if replace_extensions: return fname.lower().endswith(replace_extensions) return True def file_replace(fname, pat, s_after): # first, see if the pattern is even in the file. with open(fname) as f: if not any(re.search(pat, line) for line in f): return # pattern does not occur in file so we are done. # pattern is in the file, so perform replace operation. with open(fname) as f: out_fname = fname + ".tmp" out = open(out_fname, "w") for line in f: out.write(re.sub(pat, s_after, line)) out.close() os.rename(out_fname, fname) def mass_replace(dir_name, s_before, s_after, replace_extensions=DEFAULT_REPLACE_EXTENSIONS): pat = re.compile(s_before) for dirpath, dirnames, filenames in os.walk(dir_name): for fname in filenames: if try_to_replace(fname, replace_extensions): fullname = os.path.join(dirpath, fname) file_replace(fullname, pat, s_after) if len(sys.argv) != 4: u = "Usage: mass_replace   \n" sys.stderr.write(u) sys.exit(1) mass_replace(sys.argv[1], sys.argv[2], sys.argv[3]) 

EDITAR: He cambiado el código anterior de la respuesta original. Hay varios cambios. Primero, mass_replace() ahora llama a re.compile() para re.compile() el patrón de búsqueda; segundo, para verificar qué extensión tiene el archivo, ahora pasamos una tupla de extensiones de archivo a .endswith() lugar de llamar a .endswith() tres veces; tercero, ahora usa la statement with disponible en versiones recientes de Python; y, finalmente, file_replace() ahora comprueba si el patrón se encuentra dentro del archivo, y no reescribe el archivo si no se encuentra el patrón. (La versión anterior reescribiría todos los archivos, cambiando las marcas de tiempo incluso si el archivo de salida era idéntico al archivo de entrada; esto no era elegante).

EDITAR: Cambié esto a predeterminado para reemplazar cada archivo, pero con una línea puede editar para limitarlo a extensiones particulares. Creo que reemplazar cada archivo es un valor predeterminado más útil y listo para usar. Esto podría extenderse con una lista de extensiones o nombres de archivos que no se tocan, opciones para que no distingan mayúsculas y minúsculas, etc.

EDITAR: En un comentario, @asciimo señaló un error. Edité esto para corregir el error. Se documenta que str.endswith() acepta una tupla de cadenas, pero no una lista. Fijo. Además, hice que un par de funciones acepten un argumento opcional para permitirle pasar una tupla de extensiones; debería ser bastante fácil modificar esto para aceptar un argumento de línea de comandos para especificar qué extensiones.

¿Realmente necesitas expresiones regulares?

 import os def recursive_replace( root, pattern, replace ) for dir, subdirs, names in os.walk( root ): for name in names: path = os.path.join( dir, name ) text = open( path ).read() if pattern in text: open( path, 'w' ).write( text.replace( pattern, replace ) ) 

Por supuesto, si solo quieres hacerlo sin tener que codificarlo, usa find y xargs:

 find /home/noa/Desktop/codes -type f -print0 | \ xargs -0 sed --in-place "s/dbname=noa user=noa/dbname=masi user=masi" 

(Y es probable que puedas hacer esto con find -exec o algo así, pero prefiero xargs).

Así es como encontraría y reemplazaría cadenas en archivos usando python. Esta es una pequeña función simple que buscará recursivamente una cadena en los directorios y la reemplazará con una cadena. También puede limitar los archivos con una cierta extensión de archivo como el ejemplo a continuación.

 import os, fnmatch def findReplace(directory, find, replace, filePattern): for path, dirs, files in os.walk(os.path.abspath(directory)): for filename in fnmatch.filter(files, filePattern): filepath = os.path.join(path, filename) with open(filepath) as f: s = f.read() s = s.replace(find, replace) with open(filepath, "w") as f: f.write(s) 

Esto te permite hacer algo como:

 findReplace("some_dir", "find this", "replace with this", "*.txt") 

Esto debería funcionar:

 import re, os import fnmatch for path, dirs, files in os.walk(os.path.abspath(directory)): for filename in fnmatch.filter(files, filePattern): filepath = os.path.join(path, filename) with open("namelist.wps", 'a') as out: with open("namelist.wps", 'r') as readf: for line in readf: line = re.sub(r"dbname=noa user=noa", "dbname=masi user=masi", line) out.write(line)