4

I have a file with more than 200 columns. As for example purpose, I am here using a file with less number of columns(9). Below is the input file (a few lines)

chr10   181243  225933  1   1   1   10  0   36
chr10   181500  225933  1   1   1   106 0   35
chr10   226069  255828  1   1   1   57  0   37
chr10   243946  255828  1   1   1   4   0   27
chr10   255989  267134  1   1   1   87  0   32
chr10   255989  282777  1   1   1   61  0   34
chr10   267297  282777  1   1   1   61  0   37
chr10   282856  283524  1   1   1   92  0   35
chr10   282856  285377  1   1   1   1   0   15
chr10   283618  285377  1   1   1   72  0   33

I want to rearrange the file such that my last column (here the 9th column) is the 4th column in the output file and then print everything else. So the output I am looking for is

chr10   181243  225933  36  1   1   1   10  0
chr10   181500  225933  35  1   1   1   106 0
chr10   226069  255828  37  1   1   1   57  0
chr10   243946  255828  27  1   1   1   4   0
chr10   255989  267134  32  1   1   1   87  0
chr10   255989  282777  34  1   1   1   61  0
chr10   267297  282777  37  1   1   1   61  0
chr10   282856  283524  35  1   1   1   92  0
chr10   282856  285377  15  1   1   1   1   0
chr10   283618  285377  33  1   1   1   72  0

On a file with fewer number of columns, I can use something like this to achieve the above output:

awk -v OFS="\t" '{print $1,$2,$3,$9,$4,$5,$6,$7,$8}'

If now I have a file with a large number of columns, how can I place the last column of the file as the 4th column and rest I print as it is?

2
  • @JeffSchaller, pretty clear from the input/output sample that column 9 should be moved and "shunted" in between columns 3 and 4, forcing the rest over one slot.
    – Wildcard
    Sep 13, 2018 at 19:44
  • In the output file, column9 are all zeroes because column 8 in the input was all zeroes Sep 13, 2018 at 19:44

2 Answers 2

7

Perl is very concise for this: split each line into words, pop off the last word and insert it at index 3 (0-based)

$ perl -lane 'splice @F, 3, 0, pop(@F); print "@F"' file | column -t
chr10  181243  225933  36  1  1  1  10   0
chr10  181500  225933  35  1  1  1  106  0
...
4

To replace the fourth field with the last field:

awk -v OFS="\t" '{ $4 = $NF; $NF=""; print }

To insert the last field before the fourth field, we have to get a little creative:

awk -v OFS="\t" '{temp=$NF; for( i=NF;i>4;i-- ) {$i=$(i-1)}; $4=temp  ; print}'

This will preserve the final field, zip through all the fields and move each one backward to the fourth forward one, and then put the desired fourth field into place:

$ echo {1..10} | awk -v OFS="\t" '{temp=$NF; for( i=NF;i>4;i-- ) {$i=$(i-1)}; $4=temp  ; print}'
1   2   3   10  4   5   6   7   8   9
2
  • 1
    No, this overwrites the value in column 4. Look at the example input/output and you'll see the intention is to leave column 4 in existence, but move it over to column 5.
    – Wildcard
    Sep 13, 2018 at 19:43
  • Alternative which inserts rather than overwrites is now provided.
    – DopeGhoti
    Sep 13, 2018 at 19:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .