martes, febrero 11, 2014

Mover cadenas en una línea con el comando sed

Sed es un útil comando para manipular cadenas de un archivo.

En mi caso me encontraba con la necesidad de alterar unas sentencias update de una sql de la siguiente forma

UPDATE VIDEOTECA SET 
    TAGS = 'CIENCIA-FICCIÓN, ESPACIO, EXTRATERRESTRES, MICROBIO, ENFERMEDAD, PLAGA, DISTRI U', DISTRIBUIDORA = NULL
WHERE (VIDEOID = 326);

Que debería convertir en:

UPDATE VIDEOTECA SET 
    TAGS = 'CIENCIA-FICCIÓN, ESPACIO, EXTRATERRESTRES, MICROBIO, ENFERMEDAD, PLAGA', DISTRIBUIDORA = 'U'
WHERE (VIDEOID = 326);

Así durante más 500 líneas.

Como podéis ver en realidad lo que quiero es coger el valor que hay tras   'DISTRI' y moverlo donde está el NULL (básicamente, para actualizar los valores de una tabla moviendo uno de los tags a una nueva columna)

SED nos permite recorrer línea a línea nuestro archivo buscando patrones y, entre otras operaciones posibles, realizar sustituciones. Para ello utiliza expresiones expresiones regulares. Como nuestra cadena está muy cerrada es fácil determinar una expresión regular que detecte la cadena que queremos mover y mediante los argumentos \1 (\2 si hubiera más expresiones) mover las partes variables a donde queramos

sed -r "s/, DISTRI (.*)', DISTRIBUIDORA = NULL/', DISTRIBUIDORA = '\1'/" archivo_origen.sql > archivo_destino.sql

Revisando rápidamente el comando

  • sed [parámetros] "s/patron/sustitucion/" archivo_origen > archivo destino
  • -r para que use las expresiones regulares extendidas
  • s para que realice las operaciones de sustituciones
  • / son los separadores
  • , DISTRI (.*)', DISTRIBUIDORA = NULL el patrón que queremos detectar, la parte en negrita detecta cualquier cadena de caracteres que previa que luego vaya seguida de ', DISTRIBUIDORA = NULL y la almacena en el token \1
  • ', DISTRIBUIDORA = '\1'el patrón por el que queremos sustuir. Usamos el token  \1 para recuperar la primera variable detectada en el patrón de búsqueda
Otro ejemplo encontrado durante el mismo desarrollo y que es algo más complicado
Cambiar este sql

UPDATE VIDEOTECA SET 
    TAGS = 'DistriSONY, Drama, Rural, Años 50, Adolescencia, Cine, Jeff Bridges, Ben Johnson', DISTRIBUIDORA = NULL
WHERE (VIDEOID = 1917);

por este otro

UPDATE VIDEOTECA SET 
    TAGS = 'Drama, Rural, Años 50, Adolescencia, Cine, Jeff Bridges, Ben Johnson', DISTRIBUIDORA = 'SONY'
WHERE (VIDEOID = 1917);

El comando

sed -r "s/Distri([A-Za-z0-9]*), (.*)', DISTRIBUIDORA = NULL/\2', DISTRIBUIDORA = '\1'/" videoteca-update.sql > videotec-distri-update.sql