in reply to How to swap columns in a csv file ?

One way. There are many

$ cat test.pl #!/pro/bin/perl use 5.012003; use warnings; use Text::CSV_XS qw( csv ); my $aoh = csv (in => *DATA, kh => \my @h); say "Head was (@h)"; # Construct new header (out of old header) my @nh = qw( column2 column1 column4 column3 ); csv (in => $aoh, headers => \@nh); __END__ column1,column2,column3,column4,column5,column6 datar1c1,datar1c2,datar1c3,datar1c4,datar1c5,datar1c6 datar2c1,"data,r2c2",datar2c3,datar2c4,datar2c5,datar2c6 datar3c1,datar3c2,"data, r3c3",datar3c4,datar3c5,datar3c6
$ perl test.pl Head was (column1 column2 column3 column4 column5 column6) column2,column1,column4,column3 datar1c2,datar1c1,datar1c4,datar1c3 "data,r2c2",datar2c1,datar2c4,datar2c3 datar3c2,datar3c1,datar3c4,"data, r3c3"

update Fixed the output in above post. I mis-pasted


Enjoy, Have FUN! H.Merijn

Replies are listed 'Best First'.
Re^2: How to swap columns in a csv file ?
by ikegami (Patriarch) on Jan 06, 2025 at 12:54 UTC

    If you're ok with dealing with header indexes instead of header names, the above the be reduced to a single command:

    csv in => \*ARGV, out => \*STDOUT, after_parse => sub { $_[1]->@* = $_[1]->@[ 1, 0, 3, 2 ] };

    The whole thing as a one-liner:

    perl -MText::CSV_XS=csv -e'csv in => \*ARGV, out => \*STDOUT, after_pa +rse => sub { $_[1]->@* = $_[1]->@[1,0,3,2] }' a.csv
Re^2: How to swap columns in a csv file ?
by xuo (Acolyte) on Jan 05, 2025 at 17:49 UTC

    Hello,

    It works very well. Thank you very much for your help.

    Next steps are :
    1) to be able to manage comments in the csv file that can be split on several lines. I do it in a way I don't like using sed.
    2) to be able to sort alphabetically 2 columns
    I'll try first on my own before I ask your help again :)

    Regards

    Xuo

      "to be able to sort alphabetically 2 columns"

      Hi, it's not completely clear what you want. Maybe it's as simple as the following, which sorts by column 1 and if there multiple instances of a value, then by column 3. See sort.

      use strict; use warnings; use Text::CSV_XS 'csv'; my $aoa = csv( in => *DATA ); my @headers = shift @$aoa; my @sorted = sort { $a->[0] cmp $b->[0] || $a->[2] cmp $b->[2] } @$aoa +; csv( in => \@sorted, headers => @headers ); __DATA__ column1,column2,column3 b,foo,v a,bar,y c,baz,w b,qux,z b,nif,x

      Output:

      column1,column2,column3 a,bar,y b,foo,v b,nif,x b,qux,z c,baz,w

      Hope this helps.

      Update: added link to doc


      The way forward always starts with a minimal test.

        Hi,

        This is exactly what I wanted to do. I'll add it in my complete script.
        Thank you again very much for your help.

        Regards.

        Xuo.

      Hi,

      Step 1 is managed by default with the code from Tux. I've removed all my dirty code.

      Xuo.

        Hi,

        Everything works fine now.
        I still have one question : how to redirect the output of the csv module :
        ex : csv (in => $aoh, headers => \@nh);
        to a file instead of stdout ?

        Regards.

        Xuo.