Как мой последний вопрос был длинным, вот сжатая версия с текущим уровнем кода.awk Выполнение программы
Реферат: Мне нужно взять входной файл с разделителями каналов, проверить наличие всех применимых типов записей, добавить отсутствующие и проверить/исправить количество подполей в каждом типе записи.
Входные записи:
AA|1234|ABCD|EDGFT|TR56BE|~BB||E5TGE|~CC|253641|84597|~DD|78HND|ACBE|||43|~EE|HISBL|78943|~FF|12345|SKIP|~GG|||TYBGFR
AA|2345|CDEF|GFHIT|48UJKK|~CC||3FKTI
типа записи и проверки файлов подсчета подполе known_flds
записей:
AA~5~req
BB~2~opt
CC~3~opt
DD~6~opt
EE~4~opt
FF~2~skp
GG~4~opt
Текущий сценарий, без коррекции подполе:
#!/usr/bin/awk -f
BEGIN { FS=OFS="~" }
FNR==NR {
dflts[$1] = create_empty_field($1,$2)
if($3 ~ /req|opt/) fld_order[++fld_cnt] = $1
fld_rule[$1] = $3
next
}
{
flds = ""
j = 1
for(i=1; i<=fld_cnt; i++) {
j = skip_flds(j)
if($j !~ ("^" fld_order[i])) fld = dflts[fld_order[i]]
else { fld = $j; j++ }
flds = flds (flds=="" ? "" : OFS) fld
}
print flds
}
function create_empty_field(name, cnt, fld, i) {
fld = name
for(i=1; i<=cnt; i++) { fld = fld "|" }
return(fld)
}
function skip_flds(fnum, name) {
name = $fnum
sub(/\|.*$/, "", name)
while(fld_rule[name] == "skp") {
fnum++
name = $fnum
sub(/\|.*$/, "", name)
}
return(fnum)
}
Моя первая попытка выполнение проверки и коррекции подполей:
#!/usr/bin/awk -f
BEGIN { FS=OFS="~" }
FNR==NR {
dflts[$1] = create_empty_field($1,$2)
if($3 ~ /req|opt/) fld_order[++fld_cnt] = $1
fld_rule[$1] = $3
next
}
{
flds = ""
j = 1
for(i=1; i<=fld_cnt; i++) {
j = skip_flds(j)
if($j !~ ("^" fld_order[i])) fld = dflts[fld_order[i]]
else { fld = fix_sub($j,$2); j++ }
flds = flds (flds=="" ? "" : OFS) fld
}
print flds
}
function create_empty_field(name, cnt, fld, i) {
fld = name
for(i=1; i<=cnt; i++) { fld = fld "|" }
return(fld)
}
function skip_flds(fnum, name) {
name = $fnum
sub(/\|.*$/, "", name)
while(fld_rule[name] == "skp") {
fnum++
name = $fnum
sub(/\|.*$/, "", name)
}
return(fnum)
}
function fix_sub(rec, num, upd, cnt) {
cnt=split(rec,a,"|")-1
upd=""
if(cnt != num)
{for(i=1;i<=$num;i++)
upd = upd a[i] "|" }
else { upd=$rec }
return(upd)
}
Приведенные выше приводили к ошибкам, когда они достигли второго типа записи. Итак, теперь я знаю, что мне нужно захватить второе значение из файла known_flds
, чтобы передать его до функции fix_sub
.
Я буду добавлять:
sub_fld[$1] = $2
В разделе FNR==NR
, но кроме того, мой мозг просто жарят, и я не могу двигаться вперед.
Я знаю как самостоятельный, область fix_sub
работает. Теперь мне просто нужно получить значение, считанное с known_flds
.
Нужный выход:
AA|1234|ABCD|EDGFT|TR56BE|~BB||~CC|253641|84597|~DD|78HND|ACBE|||43|~EE|HISBL|78943||~GG|||TYBGFR
AA|2345|CDEF|GFHIT|48UJKK|~BB||~CC||3FKTI|~DD||||||~EE||||~GG|||
Оригинальный вопрос: UNIX Shell Script Solution for formatting a pipe-delimited, segmented file
Если записи разделены символом '' 'и поля разделяются' '' во входном файле, то вы должны, вероятно, сказать 'awk' тоже сделать это (например,' RS = "~" FS = "|" ') , Затем вы получаете более естественную операцию по записям и полям. Так как это верно только для ввода (а не файла поля), вы можете установить их в командной строке, как этот 'awk '