2

I have a line of code I want to use, but I want it to loop through all the columns in a file, I can do it outside of awk but its really slow. My problem is that I'm not good at looping inside awk, I can run a simple awk loop but this needs something that I can't do yet. So if you can explain how you solve this question it will help me in the future.

The awk command at the moment will output the percentage equivalent of each integer within the selected column ($i). This is the current awk command: awk -F ',' -v x=$i 'FNR==NR{s+=$x;next;} {printf "%s\n",100*$x/s}' File File

Example input for the above command:

1    
4    
3    
2    

Example output for the above command:

10.00000    
40.00000    
30.00000        
20.00000        

I need to loop in awk for all of the columns in the file (the file column number is unknown)

so if the input had more than one column, the example input could be:

1,4,2    
4,4,1  
3,1,6    
2,1,1    

Example output:

10.00000,40.00000,20.00000    
40.00000,40.00000,10.00000  
30.00000,10.00000,60.00000    
20.00000,10.00000,10.00000    

This is the attempt I made (below), obviously its wrong, I tried running a loop for both sections but that didn't give me any output at all.

awk -F"," 'NR==FNR { for (i=1;i<=NF;i++) {s+=$i;next;} next } { for (i=1;i<=NF;i++)printf "%s%%\n",100*$i/s }' File File
  • Does this help? Looping over input fields as array – Eduardo Trápani May 27 at 21:00
  • Unfortunately not, but thanks for the link. I can do a basic awk loop, but I get lost when it comes to implementing it in the above code. as its reading in the file twice, going through the columns both times, once for the sums and then again to calc the percentages – Giles May 27 at 21:06
  • Why don't you post that code, the one that's not working? People here are a lot more likely to help you fix your code than to write it for you. – Eduardo Trápani May 27 at 21:08
  • I've put one of my more successful attempts in my question now, but its a little embarrassing – Giles May 27 at 21:23
3

You were not far. But putting next inside the for loop was a blunder, because that next would be triggered right on the first field, going to the next line and ignoring the other fields of the line.

awk -F ',' '
    NR==FNR{
        for(i=1;i<=NF;i++){s[i]=s[i]+$i}
        next
    }
    {
        for(i=1;i<NF;i++){printf "%f,",100*$i/s[i]}
        printf "%f\n",100*$NF/s[NF]
    }
' File File

s in your attempt is a normal variable, but it should be an array. So that s[i] contains the sum of the column i after the file has been parsed once.

See that the last loop is to NF not inclusive, because after all fields except the last a comma should be printed. After the last field, a newline should be printed.

Output:

10.000000,40.000000,20.000000
40.000000,40.000000,10.000000
30.000000,10.000000,60.000000
20.000000,10.000000,10.000000

Should you need any clarification, just leave a comment.

| improve this answer | |
  • 1
    Thanks Quasimodo, I really appreciate the explanation – Giles May 27 at 21:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.