Modifique registros em arquivos de largura fixa

1

Eu tenho vários arquivos de largura fixa com a estrutura 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

Eles precisam ser modificados para isso:

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

i.e. se o número de um registro na coluna # 4 for < = 11, ele deve adicionar 10; se for entre 12 e 15, deve alterar o valor da coluna # 3 para B e começar a numeração na coluna # 4 de 1, se for > = 16, deve alterar o valor da coluna # 3 para C e começar a numeração em coluna # 4 de 1.

Os números específicos são apenas exemplos, os valores na coluna # 4 sobem para 900. Quaisquer outras colunas não são alteradas, basta manter as larguras fixas originais das colunas.

Existem cerca de 5000 registros em um arquivo, 5000 arquivos em uma subpasta e 50 subpastas no 'banco de dados'.

    
por Xoden 01.06.2017 / 14:48

2 respostas

2

Solução

gawk :

Script

modify_records.awk :

#!/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

A saída:

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
    
por 01.06.2017 / 16:15
1

Com o 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

Saída:

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
    
por 01.06.2017 / 19:10