Cómo repetir el valor de la columna si la celda de la siguiente línea está vacía

Cómo repetir el valor de la columna si la celda de la siguiente línea está vacía

Fichero de entrada

CARD   SG   CLASS   ATT  
11      0   DAS     YES 
CARD   SG   CLASS   ATT
12      0   ECT     YES
CARD   SG   CLASS   ATT
13      0   VAS     YES
        1   DAS     NO
CARD   SG   CLASS   ATT
14      0   SAT     YES
CARD   SG   CLASS   ATT
15      0   CDT     YES
        1   VEG     YES
        2   GAT     NO

Esperar resultado:

 CARD   SG   CLASS   ATT
 11     0   DAS      YES    
 12     0   ECT      YES
 13     0   VAS      YES
 13     1   DAS      NO
 14     0   SAT      YES
 15     0   CDT      YES
 15     1   VEG      YES
 15     2   GAT      NO

Que he hecho:

awk ' /YES|NO/{VAL=$1};/ATT/{Print "CARD" "SG" "CLASS" "ATT" };/YES|NO/{ print VAL, $2, $3, $4} ' SCGR.txt  | column -t   

11  0    DAS  YES
12  0    ECT  YES
13  0    VAS  YES
1   DAS  NO
14  0    SAT  YES
15  0    CDT  YES
1   VEG  YES
2   GAT  NO

Por favor ayudame

Respuesta1

Pruebe esto (suponiendo que todas las filas del encabezado sean exactamente iguales):

awk '  NR==1{header=$0; count=NF; print; next}
       ($0~header) {next}
       (NF==count) {col1=$1}
       (NF<count)  {printf("%s",col1)}
       1 ' infile | column -t

Respuesta2

Depurando su único delineador - Varios problemas menores:

  • Print--print
  • /ATT/{Print "CARD" "SG" "CLASS" "ATT" }-- /ATT/{print}o/ATT/;
  • /YES|NO/{VAL=$1}También se activa en los registros de los 3 campos, limpiando el valor previamente guardado. (cambiar el orden o $4 ~ /YES|NO/)

Una variante:

awk 'NF==4{v=$1;print} NF==3{print v,$0}' 

eliminando encabezados adicionales y sangría:

awk '/^CARD/ && NR>1 { next } 
     NF==4           { v=$1;print } 
     NF==3           { print v,$0 }'

Respuesta3

Si no nos importa la alineación de las columnas y solo queremos datos normalizados separados por espacios en blanco, el patrón básico es:

awk -F' +' '{ $1 = ($1 ~ /^$/ ? prev : $1); prev = $1; print }'

Mira, si configuramos un separador de campos personalizado que no es igual al espacio predeterminado, logramos una verdadera separación de campos. Si el registro comienza con una coincidencia para el separador, entonces se delimita un campo vacío.

De forma predeterminada, Awk no se separa; tokeniza: extrae de cada registro tokens que son secuencias de uno o más caracteres que no están en blanco o que no son de nueva línea. Esto significa que se ignoran los espacios en blanco/nuevas líneas iniciales y finales. Por lo tanto, si le falta una columna 1, el valor de la columna 2 se convierte en la columna 1.

Con nuestra / +/expresión regular separadora, obtenemos un verdadero comportamiento de separación. Un registro con espacios iniciales y finales como 1 2 3 4se trata como <SEP>1<SEP>2<SEP>3<SEP>4<SEP>. Así, hay seis campos: "", "1", ..., "4", "". Hay un campo antes del primero <SEP>y después del último.

Por cierto, si al primer registro le falta un campo, obviamente necesitamos un valor predeterminado para prev. Tampoco queremos que la lógica se aplique a los títulos. También reemplacemos el operador ternario con if: Así:

awk 'BEGIN { FS = " +"; prev = 0 }
     NR == 1
     NR > 1 { if ($1 == "") $1 = prev
              print
              prev = $1 }'
FOO BAR BAZ
FOO BAR BAZ
  2 3 4
0 2 3 4
1 2 3 4
1 2 3 4
  2 3 4
1 2 3 4

Respuesta4

solo para educacionsedla decisión

sed '
    1b                             #output 1st line (header)
    $!N                            #add next line to operate 2 lines altogether
    s/\(.*\)\n\(CARD.*\)/\2\n\1/   #move line with CARD to first place 
    /^CARD/D                       #delete line with CARD and go to start
    s/^\(\([0-9]*\s*\).*\n\)\s\s*/\1\2/ 
                                   #repeat 1st field of 1st line if empty in 2nd
    /\n/{P;D}                      #print&remove 1st line, go to start 
    '

información relacionada