由于我最后一个问题变得越来越长了,这里是当前代码级别的精简版本。
简介:我需要inputpipe道分隔的input文件,检查以确保所有适用的loggingtypes存在,添加缺less的任何内容,并validation/更正每个loggingtypes中的子字段数。
inputlogging:
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
loggingtypes和子字段计数validation文件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 ) }
我最初尝试执行子字段的validation和更正:
#!/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) }
上面的结果在达到第二个loggingtypes时出错。 所以现在我知道我需要从known_flds
文件中捕获第二个值,以便将其传递给fix_sub
函数。
我会join:
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|||
原始问题: 用于格式化pipe道分隔的分段文件的UNIX Shell Script解决scheme
试试这个修改的脚本:
#!/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 subfld_cnt[$1] = $2 } 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); j++ } flds = flds (flds=="" ? "" : OFS) fld } print flds } function get_field_name(fnum, name) { name = $fnum sub(/\|.*$/, "", name) return( name ) } 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 = get_field_name(fnum) while(fld_rule[name] == "skp") { fnum++ name = $fnum sub(/\|.*$/, "", name) } return( fnum ) } function fix_sub(fnum, name, cnt, a, scnt, i, upd) { name = get_field_name(fnum) cnt = split($fnum, a, "|")-1 scnt = subfld_cnt[ name ] if(cnt != scnt) { for(i=1;i<=scnt;i++) upd = upd a[i] "|" return( upd ) } return( $fnum ) }
关键区别:
subfld_cnt[$1] = $2
已被添加到FNR==NR
块中的req|opt
部分(处理known_flds
文件) get_field_name()
函数,它返回由它的fnum
参数指定的字段的第一个子字段。 skip_flds()
调用skip_flds()
fix_sub()
只接受fnum
(所有其他变量都是本地函数),并根据需要修改子字段的数量。 现在对它的调用只需要在fix_sub(j)
使用j
参数。 fix_sub()
更改的细分:
name = get_field_name(fnum)
获取查找的字段名称 split
$fnum
,并得到分裂的计数(离开你的-1调整) scnt = subfld_cnt[ name ]
从已添加到known_flds
文件处理中的数组中获取所需的字段数。 这是你失踪的主要部分。 cnt != scnt
修复子域时。 upd
设置代码中,但删除了upd = ""
– 这已经完成了局部变量。 else
值。 我得到以下内容:
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
|
这不完全符合您所需的输出。 最后的区别在于|
在GG
领域。 我认为你想要的输出是缺少的。 否则,最终字段的最后一个管道只需要在所有其他处理之后被丢弃。