awk question

Please help me with this ...

Input file

N_DC_Fabric_A,AU_SAP01,c050760169900000(*),50060169472007fc(*),50060160472007fc(*),
N_DC_Fabric_A,AU_SAP02,c050760169900004,50060169472007fc(*),50060160472007fc(*),
N_DC_Fabric_A,AU_SAP03,c050760169900004,50060169472007fc,50060160472007fc,

Output needed

N_DC_Fabric_A,AU_SAP01,c050760169900000(*),50060169472007fc(*),50060160472007fc(*),CONNECTED
N_DC_Fabric_A,AU_SAP02,c050760169900004,50060169472007fc(*),50060160472007fc(*),PARTIAL
N_DC_Fabric_A,AU_SAP03,c050760169900004,50060169472007fc,50060160472007fc,OFFLINE

Basically if () = NF-2 add CONNECTED as last column
if (
) < NF-2 add PARTIAL as last column
if no (*) at all , then add OFFLINE

where NF = number of fields

Thanks

awk -F, '
        {
                for ( i = NF; i >= 3; i-- )
                {
                        if ( $i ~ /\(\*\)/ )
                                ++c
                }
                if ( c == 3 )
                        $NF = "CONNECTED"
                if ( c >= 1 )
                        $NF = "PARTIAL"
                if ( c == 0 )
                        $NF = "OFFLINE"
                c = 0
        }
        1
' OFS=, file

Thanks for the quick response ... but i am getting this

N_DC_Fabric_A,AU_SAP01,c050760169900000(*),50060169472007fc(*),50060160472007fc(),PARTIAL
N_DC_Fabric_A,AU_SAP02,c050760169900004,50060169472007fc(*),50060160472007fc(
),PARTIAL
N_DC_Fabric_A,AU_SAP03,c050760169900004,50060169472007fc,50060160472007fc,OFFLINE

The first line should be CONNECTED

Sorry, my bad!

Correction:

awk -F, '
        {
                for ( i = NF; i >= 3; i-- )
                {
                        if ( $i ~ /\(\*\)/ )
                                ++c
                }
                if ( c == 3 )
                        $NF = "CONNECTED"
                if ( c >= 1  && c < 3 )
                        $NF = "PARTIAL"
                if ( c == 0 )
                        $NF = "OFFLINE"
                c = 0
        }
        1
' OFS=, file
1 Like

thanks again .... this works fine ,,for the above example ... but in my orignal file Number of fields are not fixed .... they vary .. i need the following logic to work

f () = NF-2 add CONNECTED as last column
if (
) < NF-2 add PARTIAL as last column
if no (*) at all , then add OFFLINE

where NF = number of fields

another example

N_DC_Fabric_A,AU_SAP01,c050760169900000(*),50060169472007fc(*),50060160472007fc(*),PARTIAL
N_DC_Fabric_A,AU_SAP02,c050760169900004,50060169472007fc(*),50060160472007fc(*),PARTIAL
N_DC_Fabric_A,AU_SAP03,c050760169900004,50060169472007fc,50060160472007fc,OFFLINE
N_DC_Fabric_A,AU_SAP011,c050760169900000(*),50060169472007fc(*),CONNECTED

Here's how to do it in general:

$ cat test.awk
BEGIN { FS=OFS="," }
{n=0; for (i=1;i<=NF;i++) {($i ~ /(*)/) && n++}}
{ print "Fields: " NF, " Matches: " n}
n == 0    {$NF="OFFLINE"}
n <  NF-3 {$NF="PARTIAL"}
n == NF-3 {$NF="CONNECTED"}
n  > NF-3 {$NF="ERROR"}
{print}

I've included a diagnostic line { print "Fields: " NF, "Matches: " n} to help point out what I think is a problem with the specification, see below. You can comment out the diagnostic line with # comment character.

I also included an ERROR line n > NF-3 {$NF="ERROR"} just in case that condition ever occurs. You could also have it print an error message there and exit. If the error condition is impossible, you can delete that line.

Anyway, back to the problem with the specification, assume the input file is the following, as you just posted:

$ cat input
N_DC_Fabric_A,AU_SAP01,c050760169900000(*),50060169472007fc(*),50060160472007fc(*),
N_DC_Fabric_A,AU_SAP02,c050760169900004,50060169472007fc(*),50060160472007fc(*),
N_DC_Fabric_A,AU_SAP03,c050760169900004,50060169472007fc,50060160472007fc,
N_DC_Fabric_A,AU_SAP011,c050760169900000(*),50060169472007fc(*),

When we run the awk script, here is what it produces, along with the diagnostic messages:

$ awk -f test.awk input
Fields: 6, Matches: 3
N_DC_Fabric_A,AU_SAP01,c050760169900000(*),50060169472007fc(*),50060160472007fc(*),CONNECTED
Fields: 6, Matches: 2
N_DC_Fabric_A,AU_SAP02,c050760169900004,50060169472007fc(*),50060160472007fc(*),PARTIAL
Fields: 6, Matches: 0
N_DC_Fabric_A,AU_SAP03,c050760169900004,50060169472007fc,50060160472007fc,PARTIAL
Fields: 5, Matches: 2
N_DC_Fabric_A,AU_SAP011,c050760169900000(*),50060169472007fc(*),CONNECTED

The last record is CONNECTED. It has 5 fields (2 matches). awk counts the end of the line after the last comma as a field. I think maybe you were counting that last record as having 4 fields. So I would suggest the condition for CONNECTED is NF-3 instead of NF-2. I hope that makes sense.

The first record is also CONNECTED, I think, NOT PARTIAL as you had in the last post. The line has 6 fields (3 matches).

In any case, the first and last record should be both be the same (either CONNECTED or PARTIAL) I think, because the last record has one more field, and has one more match, so both sides of the matches == NF - N equation increase.

One more thing. If some of the lines do not end with a comma, the awk script will not work correctly. If there is any question, to be safe, you could always run sed -e "s/ *$//" -e "s/[^,]$/&,/" on the file first.

1 Like

Another way to count without looping

awk '{f=gsub(",", "");m=gsub("\*", "")} {print "Fields",f", Match",m}' input
or
awk '{print "Fields",gsub(",", "")", Match",gsub("\*", "")}' input

Fields 5, Match 3
Fields 5, Match 2
Fields 5, Match 0
Fields 4, Match 2
1 Like

Give this a shot:

awk -F, 'BEGIN  {split ("offline partial connected", STAT, " ")}
                {n = gsub("\(\*\)","&")
                 if (n) n=(NF-n-3)?1:2
                 print $0, STAT[n+1]
                }
        ' file
N_DC_Fabric_A,AU_SAP01,c050760169900000(*),50060169472007fc(*),50060160472007fc(*), connected
N_DC_Fabric_A,AU_SAP02,c050760169900004,50060169472007fc(*),50060160472007fc(*), partial
N_DC_Fabric_A,AU_SAP03,c050760169900004,50060169472007fc,50060160472007fc, offline
1 Like

Waoo this was nice...

{split ("offline partial connected", STAT, " ")}

Creates a array with name STAT where 1="offline" 2="partial" 3="connected"

{n = gsub("\(\*\)","&")

Counts the stars *

if (n) n=(NF-n-3)?1:2

Compare the stars against the number of fields and give n correct value

print $0, STAT[n+1]

Print the original line and add status at end from the array STAT

2 Likes

Thanks Jotne for your comment and explanation of my code!