首页 > 解决方案 > awk 根据模式转置行并在之后移动(复制)剩余的列

问题描述

如何解决强制模式为“nick”的问题,基于它转置为列和模式“MY_”或“MN_”,旁边有“MX_”(MX_ 模式应位于输入文件中每个“尼克”部分)

尝试了这个 基于模式的 awk 转置行,并在填充空字段的当前列之前移动(复制), 但它限制了我想要实现的目标

输入文件:

NICK: MY_JEFF
MX_NOAA; NOBASE-INDEX_OUT_FIF;
SYS-BRAVO_X3; BASE-TREE_OUT_OUT;
A4:82:8; SEAT_25;
SYS-BRAVO_X2
NICK: MN_CAPTAIN
A4:82:8; NOBASE-INDEX_OUT_FIF;
SYS-BRAVO_X1; BASE-TREE_OUT_OUT;
MX_NOOI

所需的输出:

NICK MY_JEFF MX_NOAA NOBASE-INDEX_OUT_FIF
NICK MY_JEFF MX_NOAA SYS-BRAVO_X3 
NICK MY_JEFF MX_NOAA BASE-TREE_OUT_OUT 
NICK MY_JEFF MX_NOAA A4:82:8 
NICK MY_JEFF MX_NOAA SEAT_25 
NICK MY_JEFF MX_NOAA SYS-BRAVO_X2
NICK MN_CAPTAIN MX_NOOI A4:82:8
NICK MN_CAPTAIN MX_NOOI NOBASE-INDEX_OUT_FIF
NICK MN_CAPTAIN MX_NOOI SYS-BRAVO_X1 
NICK MN_CAPTAIN MX_NOOI BASE-TREE_OUT_OUT

标签: awkpattern-matchingfieldmultiple-columnstranspose

解决方案


$ cat tst.awk
BEGIN { FS=": |([; ]+)" }
$1 == "NICK" { prt() }
{
    for (i=1; i<=NF; i++) {
        rec[++nf] = $i
    }
}
END { prt() }

function prt(   i, hdr) {
    for (i=3; i<=nf; i++) {
        if ( rec[i] ~ /^MX/ ) {
            break
        }
    }
    hdr = rec[1] OFS rec[2] OFS rec[i]
    delete rec[i]
    for (i=3; i<=nf; i++) {
        if ( rec[i] ~ /[^[:space:]]/ ) {
            print hdr, rec[i]
        }
    }
    delete rec
    nf = 0
}

$ awk -f tst.awk file
NICK MY_JEFF MX_NOAA NOBASE-INDEX_OUT_FIF
NICK MY_JEFF MX_NOAA SYS-BRAVO_X3
NICK MY_JEFF MX_NOAA BASE-TREE_OUT_OUT
NICK MY_JEFF MX_NOAA A4:82:8
NICK MY_JEFF MX_NOAA SEAT_25
NICK MY_JEFF MX_NOAA SYS-BRAVO_X2
NICK MN_CAPTAIN MX_NOOI A4:82:8
NICK MN_CAPTAIN MX_NOOI NOBASE-INDEX_OUT_FIF
NICK MN_CAPTAIN MX_NOOI SYS-BRAVO_X1
NICK MN_CAPTAIN MX_NOOI BASE-TREE_OUT_OUT

推荐阅读