Cómo grep y reemplazar

Necesito buscar recursivamente una cadena especificada dentro de todos los archivos y subdirectorios dentro de un directorio y reemplazar esta cadena con otra cadena.

Sé que el comando para encontrarlo podría verse así:

grep 'string_to_find' -r ./* 

Pero, ¿cómo puedo reemplazar cada instancia de string_to_find con otra cadena?

Otra opción es usar find y luego pasarlo a través de sed.

 find /path/to/files -type f -exec sed -i 's/oldstring/new string/g' {} \; 

Tengo la respuesta.

 grep -rl matchstring somedir/ | xargs sed -i 's/string1/string2/g' 

Esto funciona mejor para mí en OS X:

 grep -r -l 'searchtext' . | sort | uniq | xargs perl -e "s/matchtext/replacetext/" -pi 

Fuente: http://www.praj.com.au/post/23691181208/grep-replace-text-string-in-files

Incluso podrías seguir así …

Ejemplo

 grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g' 

Esto buscará la cadena ‘ windows ‘ en todos los archivos relativos al directorio actual y reemplazará ‘ windows ‘ con ‘ linux ‘ por cada aparición de la cadena en cada archivo.

Otras soluciones mezclan syntax regex. Para usar patrones perl / PCRE tanto para buscar como para reemplazar, y evitar el procesamiento de cada archivo, esto funciona bastante bien:

 grep -rlZP 'match1' | xargs -0r perl -pi -e 's/match2/replace/g;' 

donde match1 y match2 suelen ser idénticos, pero match1 se puede simplificar para eliminar funciones más avanzadas que solo son relevantes para la sustitución, por ejemplo, grupos de captura.

Traducción: grep recursivamente y liste los archivos coincidentes, separados por nul para proteger cualquier carácter especial en el nombre de archivo, que coincida con este patrón PCRE, luego canalice esos nombres de archivo a xargs que espera una lista separada por nulos, pero no hará nada si no se reciben los nombres, y obtener perl para reescribir cada archivo, sustituyendo las líneas donde se encuentran las coincidencias.

Agregue la opción I a grep para ignorar los archivos binarios, también.

Usualmente no con grep, sino con sed -i 's/string_to_find/another_string/g' o perl -i.bak -pe 's/string_to_find/another_string/g' .

Otra opción sería usar perl con globstar.

Habilitar shopt -s globstar en su .bashrc (o en cualquier otro lugar) permite que el ** patrón global coincida con todos los subdirectorios y archivos recursivamente.

Por lo tanto, al usar perl -pXe 's/SEARCH/REPLACE/g' -i ** se sustituirá recursivamente SEARCH con REPLACE .

La bandera -X le dice a Perl que “desactive todas las advertencias”, lo que significa que no se quejará de los directorios.

El globstar también le permite hacer cosas como sed -i 's/SEARCH/REPLACE/g' **/*.ext si desea reemplazar SEARCH con REPLACE en todos los archivos secundarios con la extensión .ext .

¡Ten mucho cuidado cuando uses find y sed en un git repo! Si no excluye los archivos binarios, puede terminar con este error:

 error: bad index file sha1 signature fatal: index file corrupt 

Para resolver este error, debe revertir el sed reemplazando su new_string con su old_string . Esto revertirá las cadenas reemplazadas, por lo que volverá al principio del problema.

La forma correcta de buscar una cadena y reemplazarla es omitir find y usar grep en su lugar para ignorar los archivos binarios:

 sed -ri -e "s/old_string/new_string/g" $(grep -Elr --binary-files=without-match "old_string" "/files_dir") 

Créditos para @hobs