I have a file like this

gene    -   chr7    55675   55676   100 100
gene    -   chr7    55678   55679   100 100
gene    -   chr7    55683   55686   NP  100

The file is tab separated.

I want to change the file such that column 5 should be at column 4 and column 4 at column 5 and after that print all the columns as it is. I am showing you only 2 columns after 5th column, but there can be many more.

I tried cut -f 1,2,3,5,4,6- but it does not work.

I would prefer an awk solution for it.



To swap fields 4 and 5:

$ awk -F'\t' '{a=$4; $4=$5; $5=a;} 1' OFS='\t' file
gene    -       chr7    55676   55675   100     100
gene    -       chr7    55679   55678   100     100
gene    -       chr7    55686   55683   NP      100

How it works:

  • -F'\t'

    This sets the field separator on input to a tab.

  • a=$4; $4=$5; $5=a

    This swaps the fourth and fifth fields.

  • 1

    This is awk's cryptic shorthand for print-the-line.

  • OFS='\t'

    This tells awk to use a tab as the field separator on output.

Leaving the header unchanged

To swap the fields on all lines except the first:

awk -F'\t' -v OFS='\t' 'NR>1{a=$4; $4=$5; $5=a;} 1' file

NR is the line number. The NR>1 placed before the swap commands is a condition. The swap commands will be performed only if the condition is true.

Alternate style

Some stylists recommend that the assignment to OFS be before the code:

awk -F'\t' -v OFS='\t' '{a=$4; $4=$5; $5=a;} 1' file
  • That works, thanks. Can you tell me how to print the first line which is the header as it is and start the above calculation from 2nd line onwards? – user3138373 Sep 14 '16 at 19:28
  • @user3138373 See update for code that leaves the header unchanged. – John1024 Sep 14 '16 at 19:30

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.