
У меня есть несколько файлов фиксированной ширины со следующей структурой:
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
таращитьсярешение:
изменить_записи.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