sobre exportar globals con ^%GOGEN
La utilidad ^%GOGEN nos permite sacar a disco dentro de la red donde se encuentre el servidor de Caché GLOBALS o ficheros de la base de datos. Permite sacar uno o varios a la vez.
El formato que tiene si lo editamos es parecido a esto:
Transferring files on Mar 30 2019 at 10:24 AM ^ALD(20190330 ^ALD(20190330,"A",99730) 20190330#20190330#20190330#392224##3020#0##1##1#1#N#500#1# 9:01# 9:01##TLP1####S##3#0#0###N#S##2#D##N###A######0#0#0#0#0#0#0#0#0#0#0#0#0#0###0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#######1############################### ^ALD(20190330,"A",99730,"CP",1) 3#BONIFICACION TERMINAL#1###F#L#A#N###S# ^ALD(20190330,"A",99730,"CT") TER GZA EL#AV TRE 25#ZAMORA#49008#49#ZAMORA#P1#VALLADOLID#46P#1#49
Como se ve hay unas líneas en las que figuran los índices de los globals y otras que son lo datos. Los índices de un global pueden ser desde 0 a varios, lo mismo que los campos de datos.
problemas para obtener los datos en csv
Se trata de obtener ficheros csv que se puedan tratar por ejemplo en excel. Como los índices son variables por cada número de ellos tendremos distintos ficheros, así para el ejemplo de arriba obtendremos 3 ficheros. Uno para los registros que tienen 3 índices, otro para los de 4 y otro para los de 5.
En principio me pareció fácil hacerlo con 'bash' pero luego no resultó así. Hay varios problemas:
-
quería luego sacar los ficheros csv con una cabecera que indicara los campos que son índices de los que no. Y además cada fichero puede tener registros de cantidad variable de campos. Es decir. Dentro del fichero de 3 índices hay registros con 5 campos de datos, otros con 10 y otros con 116. La obtención de la cabecera correcta se complica. Quiero algo así:
Index1;Index2;Index3;Data1;Data2;Data3;Data4;Data5;Data6;Data7;Data8;Data9;...
-
Y otro problema grande es cuando en el %GOGEN se exportan varios ficheros. Hay que localizar dentro de cada fichero el global que es. Quitar los "^" y los "()"
En resúmen. Si tengo que hacerlo ahora quizá empezaría con 'Python' o 'Go'.
Lo que te ahorras en 'bash' es todo lo referente a apertura y escritura
de ficheros que lo haces con un simple echo "registro" >> fichero
resultados
Al final obtengo los ficheros csv, varios uno por cada número de índices distintos tenga cada global ('global_ALD20190330-6.csv, global_ALD20190330-3.csv, global_ALD20190330-4.csv…').
por ejemplo:
Index1;Index2;Index3;Index4;Index5;Data1;Data2;Data3;Data4;Data5;Data6;Data7;Data8;Data9;Data10;Data11;Data12;Data13;... 20190330;"A";99730;"CP";1;3;BONIFICACION TERMINAL;1;;;F;L;A;N;;;S;
Aquí al final el código. No olvidarse de dar permisos de ejecución con 'chmod +x xglobaltocsv.sh'
#!/usr/bin/env bash # Función: dado un o varios GLOBAL exportados con ^%GOGEN de MUMPS # crea tantos ficheros csv como por índices tenga cada global # Fecha creación: 30.03.2019 # Autor: Julio Briso-Montiano # Versión: 1.0 # Detalle: # - se pide fichero exportado con %GOGEN # - se crean ficheros csv por cada global/índices # - se inserta cabecera en el csv del tipo Index1 Index2...Data1 Data2... # # # petición de datos if [ $# -eq 0 ] then echo "introduce global exportado con %GOGEN" exit fi echo -e "\nATENCIÓN: se van a borrar todos los ficheros de tipo global*.csv\n" read -p "¿estás seguro? (s/n) " vamos if [[ $vamos != "s" ]] then echo "abortado" exit fi # # variables para trabajar file=$1 sepcsv=";" global="" isindex="" detectedglobal="" declare -A fic rm global-*.csv # # leemos línea a línea while IFS= read -r line do # # primero tenemos que detectar cuándo es una línea # de índices y cuándo es de datos. # cuidado que puede haber campos de datos del tipo # ^ALD(x,y,z que parecen de índices if [[ "${line:0:18}" == "Transferring files" ]] then detectedglobal="nextline" continue fi if [[ $detectedglobal == "nextline" ]] then global="${line//[()$'\r'^]/}" echo "global found "$global detectedglobal="jump" continue fi if [[ $detectedglobal == "jump" ]] then detectedglobal="" isindex=1 continue fi # # now we have a global to work on # first el de índices line="${line//$'\r'/}" if [[ $isindex -eq 1 ]] then isindex=0 regindex="${line#*(}" comas="${regindex//[^,]}" indices="${#comas}" ((indices+=1)) # hasta aquí para averiguar los índices regindex="${regindex//[,)]/$sepcsv}" continue fi # registro de datos que unimos con el de índices y grabamos if [[ $isindex -eq 0 ]] && [[ $indices > 0 ]] then isindex=1 ficactual=${global}"_"${indices} sepas="${line//[^#]}" campos="${#sepas}" ((campos+=1)) if [[ ${campos} -gt ${fic[$ficactual]} ]] then fic[$ficactual]=$campos fi # hasta aquí para averiguar el número máximo de campos para # ese global/índice regdata="${line//#/$sepcsv}" finalreg="${regindex}""${regdata}" echo $finalreg >> "global-"$global"_"$indices".csv" fi done <"$file" # # insertamos cabecera de nombres # por cada fichero obtenido for tipos in "${!fic[@]}" do campos=${fic[$tipos]} indices="${tipos#*_}" cab="" for ((i=1; i<=$indices; i++)) do cab=$cab"Index"$i"\t" done for ((i=1; i<=$campos; i++)) do cab=$cab"Data"$i"\t" done # no POSIX sed -i "1i"$cab "global-"$tipos".csv" echo -e $cab > borrame.txt && cat "global-"$tipos".csv" >> borrame.txt && mv borrame.txt "global-"$tipos".csv" sed -i 's/;/\t/g' global-$tipos".csv" echo "Generado fichero global-"$tipos".csv" done
Tags: MUMPS, bash