Using awk to rearrange fields

Hi,

I am required to arrange columns of a file i.e make the 15th column into the 1st column.

I am doing

awk 'begin {fs=ofs=","} {print $15,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14}' ad.data>ad.csv

the problem is that column 15 gets to column 1 but it is not comma separated with the initial column 1 ...i.e column 15 and column 1 are getting sort of concatenated with a space as a delimiter....i want a comma...what should i do?

The awk command language is case sensitive. Change:

awk 'begin {fs=ofs=","} {print $15,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14}' ad.data>ad.csv

to:

awk 'BEGIN {FS=OFS=","} {print $15,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14}' ad.data>ad.csv
1 Like

Another way to reduce some typing

awk 'BEGIN {FS=OFS=","} {$1=$15FS$1;NF--} 1' ad.data>ad.csv

a much simpler way of doing it is this:

awk -F, '{$1=$15;NF--}1' OFS=, ad.data>ad.csv

This would replace the first field with 15th field and the first field would be lost.

You're right, overlooked that part. thanks.

AWK won't stop being your friend if you use whitespace to improve your code's readability :).

Regards,
Alister

Note that this is making the unstated assumption that each input line always contains exactly 15 fields. The original code seemed to be trying to end up with 15 fields no matter how many were present in the input.

The awk script here moves the fifteenth (possibly empty) field to the start of output line, but may end up with one or more output fields depending on the number of input fields.

It also assumes that decrementing NF will modify $0. Perhaps most (all?) implementations behave this way, but there are no guarantees.

Regards,
Alister

I know that decrementing NF does NOT modify $0 in awk on OS X.

1 Like

I agree that decreasing NF is not guaranteed to work with every awk (for example it works with nawk on Solaris, but not with /usr/xpg4/bin/awk ) ,
however, it does seem to modify $0 in my version of awk on OSX ( bwk version 20070501 )

---
IF there are exactly 15 columns, one could try:

awk -F, '{$1=$15 FS $1; $15=x; sub(/,$/, x)}1' OFS=, file

or

awk -F, '{f=$15; $15=x; sub(/,$/, x); print f,$0}' OFS=, file

---------edit---------

This could work if there are more than 15 fields:

awk -F, '{$1=$15 FS $1; sub("(,[^,]*){" NF-14 "}$", x)}1' OFS=, file

if your awk can use interval expressions, so it will not work with mawk and (non-POSIX nawk ) and gawk 3.x or lower needs gawk --re-interval