固定幅ファイルのレコードの変更

固定幅ファイルのレコードの変更

次のように構成された固定幅ファイルが複数あります。

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

次のように修正する必要があります。

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

つまり、列#4のレコード数が<= 11の場合は、10を追加する必要があります。 12から15の間は、列3の値をBに変更し、番号付けは列4から1から始まる必要があります。 16より大きい場合は、列3の値をCに変更し、列4#4から1から番号付けを開始する必要があります。

具体的な数値は例示に過ぎず、4列の値は最大900までです。他の列は変更されず、元の固定列幅を維持します。

ファイルには約5000のレコードがあり、サブフォルダには約5000のファイルがあり、「データベース」には約50のサブフォルダがあります。

答え1

愚かな解決策:

Record.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

使用法:

awk -f modify_records.awk datafile3248.dat

出力:

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

答え2

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

出力:

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

関連情報