GNU/Linux >> Tutoriales Linux >  >> Linux

¿Reemplazo de cadenas usando un diccionario?

¿Cuál es una buena manera de hacer reemplazos de cadenas en un archivo usando un diccionario con mucho de pares sustituyente-sustituyente? Y por mucho , en realidad me refiero a unos 20, no mucho, pero lo suficiente como para querer organizarlos ordenadamente.

Quiero recopilar todos los pares de sustituyentes y sustituyentes en un archivo dictionary.txt de una manera fácil de administrar, ya que necesito reemplazar muchas cosas, diga algo así:

"yes"      : "no"
"stop"     : "go, go, go!"
"wee-ooo"  : "ooooh nooo!"
"gooodbye" : "hello"

"high"     : "low"
"why?"     : "i don't know"

Ahora quiero aplicar estas sustituciones en algún archivo novel.txt .

Entonces quiero ejecutar magiccommand --magicflags dictionary.txt novel.txt para que todas las instancias de yes en novel.txt se reemplazan por no (así que incluso Bayesian sería reemplazado por Banoian ) y todas las instancias de goodbye en novel.txt sería reemplazado por hello y así sucesivamente.

Hasta ahora, las cadenas que necesito reemplazar (y reemplazar con) no tienen comillas (ni simples ni dobles) en ellas. (Sin embargo, sería bueno ver una solución que funcione bien con cadenas que contengan comillas, por supuesto).

sed y awk / gawk pueden hacer ese tipo de cosas principalmente, pero ¿pueden también trabajar con tales archivos de diccionario? Parece como gawk sería el candidato adecuado para magiccommand , ¿cuáles son las magicflags correctas? ? ¿Cómo necesito formatear mi dictionary.txt? ?

Respuesta aceptada:

Aquí hay una forma con sed :

sed '
s|"(.*)"[[:blank:]]*:[[:blank:]]*"(.*)"|1
2|
h
s|.*n||
s|[&/]|\&|g
x
s|n.*||
s|[[.*^$/]|\&|g
G
s|(.*)n(.*)|s/1/2/g|
' dictionary.txt | sed -f - novel.txt

Cómo funciona:
El primer sed convierte dictionary.txt en un archivo de script (comandos de edición, uno por línea). Esto se canaliza al segundo sed (tenga en cuenta el -f - lo que significa leer comandos de stdin ) que ejecuta esos comandos, editando novel.txt .
Esto requiere traducir su formato

"STRING"   :   "REPLACEMENT"

en un sed comando y escapando cualquier carácter especial en el proceso para ambos LHS y RHS :

s/ESCAPED_STRING/ESCAPED_REPLACEMENT/g

Así que la primera sustitución

s|"(.*)"[[:blank:]]*:[[:blank:]]*"(.*)"|1
2|

convierte "STRING" : "REPLACEMENT" en STRINGnREPLACEMENT (n es un carácter de nueva línea). El resultado luego se copia sobre el h antiguo espacio.
s|.*n|| elimina la primera parte manteniendo solo REPLACEMENT entonces s|[&/]|\&|g escapa los caracteres reservados (este es el RHS ).
Entonces ex cambia el búfer de espera con el patrón de espacio y s|n.*|| elimina la segunda parte manteniendo solo STRING y s|[[.*^$/]|\&|g hace el escape (este es el LHS ).
El contenido del búfer de retención se agrega al espacio de patrón a través de G así que ahora el contenido del espacio patrón es ESCAPED_STRINGnESCAPED_REPLACEMENT .
La sustitución final

s|(.*)n(.*)|s/1/2/g|

lo transforma en s/ESCAPED_STRING/ESCAPED_REPLACEMENT/g


Linux
  1. ¿Cómo habilitar el registro de error-log.txt usando el archivo .htaccess?

  2. ¿Cómo escribir una cadena de varias líneas usando Bash con variables?

  3. Usar grep para buscar una cadena que tenga un punto

  4. ¿Redirigir toda la salida al archivo usando Bash en Linux?

  5. Cómo enviar una cadena al servidor usando s_client

Cómo crear una instancia RDS usando Python Boto3 en AWS

¿Usar Sed para agregar un carácter en la posición N de la cadena coincidente?

Uso del comando Diff para comparar dos archivos en la terminal de Linux

Bash Beginner Series #4:Uso de arreglos en Bash

Uso del comando Bash printf para imprimir salidas formateadas

Uso de scp para transferir una lista de archivos de archivos .txt