Monday, November 19, 2012

How to swap 2 columns in a file in Linux?



How to swap 2 columns or fields in a text or a CSV file?

Let us consider a file with the following contents. The requirement is to swap the first 2 fields:
$ cat file
Linux,25,1
Solaris,30,2
HPUX,15,3
AIX,28,4
1. Using awk:
$ awk -F, '{print $2,$1,$3}' OFS=, file
25,Linux,1
30,Solaris,2
15,HPUX,3
28,AIX,4
Using the print statement, simply the fields can be printed in the order in which it is needed.  -F is to specify the input field separator and OFS for the output field separator. However, this method will not be ideal for a file with large number of fields since it forces us to print all columns individually.

2. awk for a file with large number of fields:
$ awk -F, 'BEGIN{OFS=FS;}{t=$i;$i=$j;$j=t;}1' i=1 j=2  file
25,Linux,1
30,Solaris,2
15,HPUX,3
28,AIX,4
The simple swapping of 2 fields using a temporary variable is done here. Two variables i and j contain the field numbers which are to be swapped. Just be setting the appropriate numbers in these 2 variables, any set of columns can be swapped. The 1 outside the braces prints every line by default. 

3. Pure Bash solution:
$ while IFS=, read x1 x2 rest
> do
>  echo ${x2},${x1},$rest
> done < file
25,Linux,1
30,Solaris,2
15,HPUX,3
28,AIX,4
The file is parsed using the while command. By setting the IFS to comma, the read command will read till every comma. And hence, the first field will be in x1, 2nd in x2 and the remaining in "rest" variable. While printing, echo first prints the 2nd followed by the 1st and then the rest. Note: This method will not be advised where swapping has to be done on fields which are not the beginning ones.

4. Perl solution:
$ perl -F, -ane 'BEGIN{$,=",";}($F[0],$F[1])=($F[1],$F[0]);print @F;' file
25,Linux,1
30,Solaris,2
15,HPUX,3
28,AIX,4
Using the auto-split(a) mode and by using comma as delimiter, every line is split into the special array @F. Just by swapping the array fields 0 & 1 and printing the entire array, we get the needed.

5. Using the join command (only for files with less fields)
$ join -t, -o 1.2,1.1,1.3 file file
25,Linux,1
30,Solaris,2
15,HPUX,3
28,AIX,4
Using the join command, the input file is joined with itself which is done just to fulfill the syntax of join where it needs 2 files to join. The -O option of join command allows us to choose the fields to display in a particular order using which we swap the fields.

1 comment:

  1. Is there any way to change the columns with sed? I want to change two columns from the back so I am trying but it is hard... My file has 3 columns total and I want to switch 2nd and 3rd column.

    ReplyDelete