texto reemplazar recorrer programacion multiplicar manipulacion especiales cortar caracteres cadenas cadena buscar bash parsing awk find

reemplazar - Cómo encontrar e imprimir un personaje específico en bash



recorrer string bash (4)

Perl al rescate!

No ha especificado cómo obtener la información del encabezado, por lo que en el siguiente guión, la matriz de encabezado @ se completa directamente.

%to_idx hash mapea los nombres de las columnas en sus índices (A => 0, B => 1, etc.).

Cada línea se divide en campos, cada campo se compara con el esperado ( $next ) y se imprimen guiones si es necesario. Lo mismo ocurre con los campos finales perdidos.

#!/usr/bin/perl use warnings; use strict; my @header = qw( A B C D E F ); my %to_idx = map +($header[$_] => $_), 0 .. $#header; open my $IN, ''<'', shift or die $!; while (<$IN>) { chomp; my @fields = split /,/; print shift @fields; my $next = 0; for my $field (@fields) { my ($name, $value) = split /=/, $field; print '',-'' x ($to_idx{$name} - $next); print ",$name=$value"; $next = $to_idx{$name} + 1; } print '',-'' x (1 + $#header - $next); # Missing trailing fields. print "/n" }

Tengo un archivo como:

AA,A=14,B=356,C=845,D=4516 BB,A=65,C=255,D=841,E=5133,F=1428 CC,A=88,B=54,C=549,F=225

Nunca sé si en la fila falta el valor A, B, C o D. Pero necesito transformar este archivo como:

AA,A=14,B=356,C=845,D=4516,-,- BB,A=65,-,C=255,D=841,E=5133,F=1428 CC,A=88,B=54,C=549,-,-,F=225

Entonces, si falta algún valor, imprima solo - marque. Mi plan tiene la misma cantidad de columnas para un análisis sencillo. Yo prefiero la solución awk. Gracias por cualquier consejo o ayuda.

Mi primer intento fue:

awk ''{gsub(/[,]/, "/t")}; BEGIN{ FS = OFS = "/t" } { for(i=1; i<=NF; i++) if($i ~ /^ *$/) $i = "-" }; {print $0}''

Pero luego noto que faltan algunos valores.

EDITAR:

Desde mi encabezado, sé que hay un valor A, B, C, D, E, F ...


Solución en TXR

@(do (defstruct fill-missing nil strings (hash (hash :equal-based)) (:postinit (self) (each ((s self.strings)) (set [self.hash s] "-"))) (:method add (self str val) (set [self.hash str] `@str=@val`)) (:method print (self stream) (put-string `@{(mapcar self.hash self.strings) ","}` stream)))) @(repeat) @ (bind fm @(new fill-missing strings ''#"A B C D E F")) @{label},@(coll)@{sym /[^,=]+/}=@{val /[^,]+/}@(do fm.(add sym val))@(end) @ (do (put-line `@label,@fm`)) @(end)

Correr:

$ txr missing.txr data AA,A=14,B=356,C=845,D=4516,-,- BB,A=65,-,C=255,D=841,E=5133,F=1428 CC,A=88,B=54,C=549,-,-,F=225


$ cat file.txt AA,A=14,B=356,C=845,D=4516 BB,A=65,C=255,D=841,E=5133,F=1428 CC,A=88,B=54,C=549,F=225 $ perl -F, -le ''@k=(A..F); $op[0]=$F[0]; @op[1..6]=("-")x6; $j=0; for($i=1;$i<=$#F;){ if($F[$i] =~ m/$k[$j++]=/){$op[$j]=$F[$i]; $i++} } print join(",",@op) '' file.txt AA,A=14,B=356,C=845,D=4516,-,- BB,A=65,-,C=255,D=841,E=5133,F=1428 CC,A=88,B=54,C=549,-,-,F=225

  • -F, divide la línea de entrada y guarda en @F array
  • -l elimina la nueva línea de la línea de entrada, agrega nueva línea a la salida
  • @k=(A..F); inicializar array @k con A , B , etc. hasta F
  • $op[0]=$F[0]; @op[1..6]=("-")x6; initalize @op array con el primer elemento de @F y los seis elementos restantes como -
  • for-loop itera sobre @F array, si el elemento coincide con el elemento @k array en el índice correspondiente seguido de = , cambia el elemento @op
  • print join(",",@op) imprime la matriz @op con , como separador

BEGIN { PROCINFO["sorted_in"]="@ind_str_asc" # order for for(i in a) for(i=65;i<=90;i++) # create the whole alphabet to array a[] a[sprintf("%c", i)] # you could read the header and use that as well } { split($0,b,",") # split record by "," printf "%s", b[1] # printf first element (AA, BB...) delete b[1] # get rid of it for(i in b) b[substr(b[i],1,1)]=b[i] # take the first letter to use as index (A=12) for(i in a) # go thru alphabet and printf from b[] printf "%s%s", OFS, (i in b?b[i]:"-"); print "" } awk -v OFS=/, -f parsing.awk tbparsed.txt AA,A=14,B=356,C=845,D=4516,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,- BB,A=65,-,C=255,D=841,E=5133,F=1428,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,- CC,A=88,B=54,C=549,-,-,F=225,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-

Imprime "-" para cada letra que no se encuentra en el registro. Si los datos tuvieran un encabezado, podría split en el arreglo 2-D b[NR] y cambiar el de for(i in a) por for(i in b[1]) ... printf ... b[NR][b[1][i]] ... y si no necesita la primera columna estática, elimine la primera printf y delete .