Search code examples
awkformattingrowslines

awk only specific rows transpose into multiple columns


Does anybody know how to transpose this input of rows in a file?

invStatus: ONLINE
System: 55
StatFail: 0
invState: 0 Unknown
invFailReason: None
invBase: SYS-MG5-L359-XO1-TRAFFIC STAT 5: TRAF2
invFlag: 0xeee5 SEMAN PRESENT STATUS H_DOWN BASE LOGIC_ONLINE DEX EPASUS INDEX ACK
dexIn: 0
dexIO: 0
badTrans: 0
badSys: 0
io_IN: 0
io_OUT: 0
Tr_in: 0
Tr_out: 0

into similar output:

invBase:   SYS-MG5-L359-XO1-TRAFFIC STAT 5: TRAF2
invFlag:   0xeee5 SEMAN PRESENT STATUS H_DOWN BASE LOGIC_ONLINE DEX EPASUS INDEX ACK
invStatus: ONLINE   System:     55    StatFail:   0     invState:    0 Unknown  invFailReason: None   
dexIn:        0     dexIO:       0    badTrans    0     badSys:      0
io_IN:        0     io_OUT:      0    Tr_in:      0     Tr_out:      0

i tried 1st time at the beginning to add at the end of each row ";" then join multiple rows > then split them based on string but still getting messy output

I am at this stage with formatting:

cat port | sed 's/$/;/g' | awk 'ORS=/;$/?" ":"\n"'

Solution

  • I'd start with this

    awk -F: '
        {data[$1] = $0}
        END {
            OFS="\t"
            print data["invBase"]
            print data["invFlag"]
            print data["invStatus"], data["System"], data["StatFail"], data["invState"], data["invFailReason"]
            print data["dexIn"], data["dexIO"], data["badTrans"], data["badSys"]
            print data["io_IN"], data["io_OUT"], data["Tr_in"], data["Tr_out"]
        }
    ' file
    
    invBase: SYS-MG5-L359-XO1-TRAFFIC STAT 5: TRAF2
    invFlag: 0xeee5 SEMAN PRESENT STATUS H_DOWN BASE LOGIC_ONLINE DEX EPASUS INDEX ACK
    invStatus: ONLINE       System: 55      StatFail: 0     invState: 0 Unknown     invFailReason: None
    dexIn: 0        dexIO: 0        badTrans: 0     badSys: 0
    io_IN: 0        io_OUT: 0       Tr_in: 0        Tr_out: 0
    

    Then, to make it as pretty as you want, start with storing the line lengths and change the print statements to printf statements using some of those lengths.


    A closer look at the file reveals that, except for 3 lines, they are sequential and can be pasted into 4 columns:

    awk -F: '
        $1 == "invBase" || $1 == "invFlag" {print; next}
        $1 == "invStatus" {invStatus = $0; next}
        {line[n++] = $0}
        END {
            printf invStatus "\t"
            paste = "paste - - - -"
            for (i=0; i<n; i++) {print line[i] | paste}
            close(paste)
        }
    ' file
    

    which provides the same output as above.