
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 4
se 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
'