
Tengo varios archivos de ancho fijo con una estructura como esta:
datafile3248.dat
HEAD
DESCRIPTION
NAME 1 A 8 X
NAME 2 A 8 X
NAME 3 A 9 XX
NAME 4 A 9 XX
NAME 5 A 9 Y
NAME 6 A 10 Y
NAME 7 A 11 XY
NAME 8 A 11 XZ
NAME 9 A 12 Z
NAME 10 A 13 Z
NAME 11 A 13 Z
NAME 12 A 13 YZ
NAME 13 A 14 ZZ
NAME 14 A 15 X
NAME 15 A 16 XX
NAME 16 A 16 X
NAME 17 A 16 Y
NAME 18 A 17 YY
Deben modificarse de esta manera:
HEAD
DESCRIPTION
NAME 1 A 18 X
NAME 2 A 18 X
NAME 3 A 19 XX
NAME 4 A 19 XX
NAME 5 A 19 Y
NAME 6 A 20 Y
NAME 7 A 21 XY
NAME 8 A 21 XZ
NAME 9 B 1 Z
NAME 10 B 2 Z
NAME 11 B 2 Z
NAME 12 B 2 YZ
NAME 13 B 3 ZZ
NAME 14 B 4 X
NAME 15 C 1 XX
NAME 16 C 1 X
NAME 17 C 1 Y
NAME 18 C 2 YY
es decir, si el número de un registro en la columna #4 es <= 11, se debe sumar 10; si está entre 12 y 15, debe cambiar el valor de la columna #3 a B y comenzar a numerar en la columna #4 desde 1, si es >=16, debe cambiar el valor de la columna #3 a C y comenzar a numerar en la columna #4 de 1.
Los números específicos son solo a modo de ejemplo, los valores en la columna 4 llegan hasta 900. El resto de columnas no se modifican, solo es necesario conservar los anchos fijos originales de las columnas.
Hay alrededor de 5000 registros en un archivo, 5000 archivos en una subcarpeta y 50 subcarpetas en la "base de datos".
Respuesta1
papar moscassolución:
modificar_records.awkguion:
#!/bin/awk -f
function pr(s, new_val) # returns new field value preserving formatting
{
len = length(s) # getting field length (including leading whitespaces)
return sprintf("%"len"s", new_val)
}
BEGIN {
FPAT = "([[:space:]]*[[:alnum:]]+)"; OFS = "" # representation of field value
}
NR > 2 { # starting from the 3rd record
if ($4 <= 11) {
$4 = pr($4, $4+10)
} else if ($4 >= 12 && $4 <= 15) {
$3 = pr($3,"B")
$4 = pr($4, $4-11)
} else if ($4 >= 16) {
$3 = pr($3, "C")
$4 = pr($4, $4-15)
}
} 1
Uso:
awk -f modify_records.awk datafile3248.dat
La salida:
HEAD
DESCRIPTION
NAME 1 A 18 X
NAME 2 A 18 X
NAME 3 A 19 XX
NAME 4 A 19 XX
NAME 5 A 19 Y
NAME 6 A 20 Y
NAME 7 A 21 XY
NAME 8 A 21 XZ
NAME 9 B 1 Z
NAME 10 B 2 Z
NAME 11 B 2 Z
NAME 12 B 2 YZ
NAME 13 B 3 ZZ
NAME 14 B 4 X
NAME 15 C 1 XX
NAME 16 C 1 X
NAME 17 C 1 Y
NAME 18 C 2 YY
Respuesta2
Con GNU awk
:
awk -v FIELDWIDTHS='4 7 3 4 4' '
NR>2 {
if ($4 <= 11)
$4 += 10
else if ($4 >= 12 && $4 <= 15) {
$3 = "B"
$4 -= 11
}
else if ($4 >= 16) {
$3 = "C"
$4 -= 15
}
$3 = sprintf("%3s", $3)
$4 = sprintf("%4d", $4)
}
1' datafile3248.dat
Producción:
HEAD
DESCRIPTION
NAME 1 A 18 X
NAME 2 A 18 X
NAME 3 A 19 XX
NAME 4 A 19 XX
NAME 5 A 19 Y
NAME 6 A 20 Y
NAME 7 A 21 XY
NAME 8 A 21 XZ
NAME 9 B 1 Z
NAME 10 B 2 Z
NAME 11 B 2 Z
NAME 12 B 2 YZ
NAME 13 B 3 ZZ
NAME 14 B 4 X
NAME 15 C 1 XX
NAME 16 C 1 X
NAME 17 C 1 Y
NAME 18 C 2 YY