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?

  • @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 '18 at 19:44
  • In the output file, column9 are all zeroes because column 8 in the input was all zeroes – user3138373 Sep 13 '18 at 19:44
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
  • 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 '18 at 19:43
  • Alternative which inserts rather than overwrites is now provided. – DopeGhoti Sep 13 '18 at 19:48

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.