Column manipulation using AWK
Column manipulation using AWK
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?
In the output file, column9 are all zeroes because column 8 in the input was all zeroes
– user3138373
Sep 13 '18 at 19:44
2 Answers
2
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
...
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
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
Thanks for contributing an answer to Unix & Linux Stack Exchange!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
@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