
次のような構造を持つ固定幅のファイルが複数あります。
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 の番号を 1 から開始します。
特定の数値は例のみであり、列 #4 の値は最大 900 になります。他の列は変更されず、列の元の固定幅を維持するだけです。
ファイルには約 5000 件のレコードがあり、サブフォルダーには 5000 件のファイルがあり、「データベース」には 50 個のサブフォルダーがあります。
答え1
驚いて見る解決:
レコードを変更する脚本:
#!/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