Awk for loop not searching all fields

Viewed 71

I'm trying to

  1. print the first 3 columns
  2. find all fields with "Eury_gr1_" and print them to the 4th column
  3. if there are no "Eury_gr1_" in the whole row print 0 in the 4th column.

Input looks like the below named "final_pcs_mod_test.csv":

PC_00001,143,143.0,Eury_gr2_(111),Eury_gr5_(19),Unk_unclust_(1),Eury_gr1_(6),MAV_eury_(6)
PC_00004,137,137.0,Eury_gr6_(20),Eury_gr11_(24),Eury_gr14_(24),Eury_gr8_(8),Eury_gr12_(13)
PC_00027,109,109.0,Eury_gr1_(80),MAV_eury_(8)

The desired output will look like the below named "eury1":

PC_00001,143,143.0,Eury_gr1_(6)
PC_00004,137,137.0,0
PC_00027,109,109.0,Eury_gr1_(80)

The command I'm using is:

awk 'BEGIN {FS=","};{for(i=4;i<=NF;i++){if($i~/^Eury_gr1_/){a=$i} else {a="0"}} print $1,$2,$3,a}' final_pcs_mod_test.csv > eury1

The actual output is:

PC_00001,143,143.0,0
PC_00004,137,137.0,0
PC_00027,109,109.0,Eury_gr1_(80)

As you can see the first row is missing a "Eury_gr1_" entry. Looks like the code is only looking in the first specified column and not searching all columns as I want. I've been messing around with for(i=4;i<=4;i++) etc... but so far cannot seem to get it to find entries in the last columns of the input. The whole input file has a max of 17 columns. What am I doing wrong?

1 Answers

Could you please try following, written and tested with shown samples in GNU awk. Output will be same as shown samples.

awk '
BEGIN{
  FS=OFS=","
}
{
  for(i=4;i<=NF;i++){
    if($i~/Eury_gr1_\([0-9]+\)/){
        found=(found?found OFS:"")$i
     }
  }
  if(found==""){ $4="0"   }
  else         { $4=found }
  print $1,$2,$3,$4
  found=""
}' Input_file

OR

awk '
BEGIN{
  FS=OFS=","
}
{
  for(i=1;i<=NF;i++){
    if(i<=3){
      val1=(val1?val1 OFS:"")$i
    }
    else if(i>3){
      if($i~/Eury_gr1_\([0-9]+\)/){
        found=(found?found OFS:"")$i
      }
    }
  }
  if(found==""){ $4="0"   }
  else         { $4=found }
  print val1,$4
  found=val1=""
}' Input_file

Explanation: Adding detailed explanation for above.

awk '                                    ##Starting awk program from here.
BEGIN{                                   ##Starting BEGIN section from here of this program.
  FS=OFS=","                             ##Setting field separator and output field separator to comma here.
}
{
  for(i=1;i<=NF;i++){                    ##Traversing through all the fields of current line here.
    if(i<=3){                            ##Checking condition if field number of lesser than or equal to 3 then do following.
      val1=(val1?val1 OFS:"")$i          ##Creating val1 and keep adding values there.
    }
    else if(i>3){                        ##else if field number is greater than 3 then do following.
      if($i~/Eury_gr1_\([0-9]+\)/){      ##Checking if current field is Eury_gr1_(digits) then do following.
        found=(found?found OFS:"")$i     ##Creating variable found and keep adding values there.
      }
    }
  }
  if(found==""){ $4="0"   }              ##Checking condition if found is NULL then make 4th field as zero.
  else         { $4=found }              ##else set found value to 4th field here.
  print val1,$4                          ##Printing val1 and 4th field here.
  found=val1=""                          ##Nullifying val1 and found here.
}' Input_file                            ##Mentioning Input_file name here.

OP's attempt fix: As per OP's comments fixing OP's attempt here. But this will match only 1 occurrence of Eury_gr1 each line, for looking for all occurrences please refer my above solution.

awk '
BEGIN{
  FS=","
}
{
  for(i=4;i<=NF;i++){
    if($i~/^Eury_gr1_\([0-9]+\)$/){ a1 }
  }
  print $1,$2,$3,a1
  a1=""
}' Input_file
Related