Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

awk command to print multiple columns using for loop

Tags:

bash

shell

awk

I am having a single file in which it contains 1st and 2nd column with item code and name, then from 3rd to 12th column which contains its 10 days consumption quantity continuously. Now i need to convert that into 10 different files. In each the 1st and 2nd column should be the same item code and item name and the 3rd column will contain the consumption quantity of one day in each..

input file:

Code  | Name | Day1 | Day2 | Day3 |... 

10001 | abcd | 5 | 1 | 9 |...    
10002 | degg | 3 | 9 | 6 |...    
10003 | gxyz | 4 | 8 | 7 |...

I need the Output in different file as

file 1:

Code  | Name | Day1

10001 | abcd | 5   
10002 | degg | 3   
10003 | gxyz | 4   

file 2:

Code  | Name | Day2

10001 | abcd | 1   
10002 | degg | 9   
10003 | gxyz | 8  

file 3:

Code  | Name | Day3

10001 | abcd | 9   
10002 | degg | 6   
10003 | gxyz | 7 

and so on....

I wrote a code like this

awk 'BEGIN { FS = "\t" } ; {print $1,$2,$3}' FILE_NAME > file1;
awk 'BEGIN { FS = "\t" } ; {print $1,$2,$4}' FILE_NAME > file2;
awk 'BEGIN { FS = "\t" } ; {print $1,$2,$5}' FILE_NAME > file3;

and so on...

Now i need to write it with in a 'for' or 'while' loop which would be faster...

I dont know the exact code, may be like this..

for (( i=3; i<=NF; i++)) ; do awk 'BEGIN { FS = "\t" } ; {print $1,$2,$i}' input.tsv > $i.tsv; done

kindly help me to get the output as i explained.

like image 269
Arun Venkitusamy Avatar asked Jun 05 '26 15:06

Arun Venkitusamy


1 Answers

If you absolutely need to to use a loop in Bash, then your loop can be fixed like this:

for ((i = 3; i <= 10; i++)); do awk -v field=$i 'BEGIN { FS = "\t" } { print $1, $2, $field }' input.tsv > file$i.tsv; done

But it would be really better to solve this using pure awk, without shell at all:

awk -v FS='\t' '
  NR == 1 {
    for (i = 3; i < NF; i++) {
      fn = "file" (i - 2) ".txt";
      print $1, $2, $i > fn;
      print "" >> fn;
    }
  }
  NR > 2 {
    for (i = 3; i < NF; i++) {
      fn = "file" (i - 2) ".txt";
      print $1, $2, $i >> fn;
    }
  }' inputfile

That is, when you're on the first record, create the output files by writing the header line and a blank line (as in specified in your question).

For the 3rd and later records, append to the files.

Note that the code in your question suggests that the fields in the file are separated by tabs, but the example files seem to use | padded with variable number of spaces. It's not clear which one is your actual case. If it's really tab-separated, then the above code will work. If in fact it's as the example inputs, then change the first line to this:

awk -v OFS=' | ' -v FS='[ |]+' '
like image 61
janos Avatar answered Jun 08 '26 09:06

janos