Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix awk程序文件执行_Unix_Awk - Fatal编程技术网

Unix awk程序文件执行

Unix awk程序文件执行,unix,awk,Unix,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|

由于我的最后一个问题越来越长,这里有一个当前代码级别的压缩版本

小结:我需要接收以管道分隔的输入文件,检查以确保所有适用的记录类型都存在,添加任何缺少的记录类型,并验证/更正每个记录类型中的子字段数

输入记录:

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
记录类型和子字段计数验证文件
已知\u fld
条目:

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 )
}
FNR==NR
部分,但除此之外,我的大脑简直是油炸了,我无法前进

我知道作为一个独立的,
fix\u sub
区域可以工作。现在我只需要获取从
known\u 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|||

原始问题:

尝试修改后的脚本:

#!/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 )
}

这与您期望的输出不完全匹配。区别在于
GG
字段中的最后一个
|
。我认为你所期望的产出没有达到。否则,在所有其他处理之后,最终字段的最终管道只需要删除。

如果输入文件中的记录由
~
分隔,字段由
|
分隔,则您可能应该告诉
awk
也这样做(即
RS=“~”FS=“|”
)。然后,您可以对记录和字段进行更自然的操作。因为这只适用于输入(而不是字段文件),所以您可以在命令行上设置这些设置,如
awk''FS='~'field_file RS='~'FS='|'input_file
,它将按您想要的方式工作。啊,如果您确实需要按行分割输入,那么这可能不太容易。。。但您可能仍然希望使用这种想法,在拆分成
~
分隔字段后,在
上使用
split()
。记录类型由
~
分隔,但它仍然需要作为一条记录读取(供sqlldr以后使用)。真正的记录分隔符应该是
RS='\n'
~BB
条目中的
E5TGE
在第一行哪里?标记字段(例如,
~BB
是否计入字段计数(即,
~BB | | | ~CC
是两个
~BB
字段)?@EtanReisner:是的,记录类型标识符在字段计数中起作用。最终的结果是由
sqlldr
使用,因此所有字段都必须进行计数。这很好!再次感谢您在解决这一棘手问题时提供的所有帮助。我可以处理最终的
。我主要不希望它出现在那里,因为se即使
sqlldr
没有在控制文件中指定它,也不会将它作为最后一列来读取,但其他可能需要处理此问题的人可能会这样做。
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|||
#!/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 )
}
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||||