gghelpneeded has asked for the wisdom of the Perl Monks concerning the following question:

fellow monks

what type of syntax would i use (not asking for script) to accomplish the following:

switch columns 2 and 3 if 2 is greater than 3 and if so add a new column to that row that has a + sign

Example Data

red 15 2 smith blue 4 10 walter

Expected Output

red 2 15 smith + blue 4 10 walter

can this be accomplished through awk? or would I use the cut command?

Replies are listed 'Best First'.
Re: switching two columns under conditions
by Corion (Patriarch) on Aug 13, 2015 at 17:07 UTC

    Let me suggest Perl, as this site is mostly about Perl.

    I would assume most of the syntax you would use is found in your course material, but also in perlsyn. Personally, I would look at perlrun and use the "autosplit" parameter, together with push and print, and the if statement.

Re: switching two columns under conditions
by stevieb (Canon) on Aug 13, 2015 at 18:02 UTC
Re: switching two columns under conditions
by james28909 (Deacon) on Aug 13, 2015 at 17:22 UTC
    Personally, I would slurp the file into an array, and then create a new array for your expected output. then I would loop through the original array comparing the second and third element, and if $_1 gt $_2 then push what data you need to the final array like:
    for(@input){ if($_[1] gt $_[2]){ push (@output, "$_[0] $_[2] $_[1] $[3] +"); } print "$_\n" for @output;
    EDIT: Sorry for the confusion, you will need to split the element if you do it this way, please take this code into consideration:
    use strict; use warnings; my @input; my @output; while (<DATA>) { push @input, $_; } for (@input) { my @temp = split( /\s+/, $_ ); # you split on a delimiter, which i +s 1 or more spaces in this case if ( $temp[1] gt $temp[2] ) { push( @output, "$temp[0] $temp[2] $temp[1] $temp[3] +" ); } else { push @output, "$temp[0] $temp[1] $temp[2] $temp[3]"; } } print "$_\n" for @output __DATA__ red 15 2 smith blue 4 10 walter
    The reason I posted the code is because I earlier told you to do it a certain way, without also telling you that you would need to use the split function and create a temporary array to store the results from the split.
Re: switching two columns under conditions (Spreadsheet::Engine)
by jeffa (Bishop) on Aug 13, 2015 at 18:59 UTC

    This would be a very silly way to accomplish this, but it works. :)

    use strict; use warnings; use Data::Dumper; use Spreadsheet::Engine; my @data = ( [qw( red 15 2 smith )], [qw( blue 4 10 walter )], [qw( blue 4 10 walter )], [qw( red 15 2 smith )], ); my @commands = ( 'set E_ formula IF(B_>C_,B_,"")', 'set F_ formula IF(B_<C_,B_,"")', 'set B_ formula IF(E_,C_,F_)', 'set F_ formula IF(B_<C_,C_,"")', 'set C_ formula IF(E_,E_,F_)', 'set E_ formula IF(F_,"","+")', 'set F_ value v', ); my $sheet = import( @data ); for my $row (0 .. $#data) { $sheet = apply( $sheet, $_, $row + 1 ) for @commands; } print Dumper [ export( $sheet ) ]; sub apply { my ($sheet, $formula, $row) = @_; $formula =~ s/_/$row/g; $sheet->execute( $formula ); $sheet->recalc; import( export( $sheet ) ); } sub import { my @data = @_; my $sheet = Spreadsheet::Engine->new; for my $row (0 .. $#data) { for my $col (0 .. $#{ $data[$row] }) { my $key = Spreadsheet::Engine::Sheet::number_to_col( $col ++ 1 ) . ( $row + 1 ); my $val = $data[$row][$col] || ''; my $type = $val =~ /\D/ ? 'v' : 'n'; $sheet->execute( "set $key value $type $val" ); } } return $sheet; } sub export { my $sheet = shift; my @data = (); for my $row (0 .. $sheet->raw->{sheetattribs}{lastrow} - 1) { my @tmp; for my $col (0 .. $sheet->raw->{sheetattribs}{lastcol} - 1) { my $key = Spreadsheet::Engine::Sheet::number_to_col( $col ++ 1 ) . ( $row + 1 ); push @tmp, $sheet->raw->{datavalues}{$key}; } push @data, [@tmp]; @tmp = (); } return @data; } __DATA__ $VAR1 = [ [ 'red', '2', '15', 'smith', '+', '' ], [ 'blue', '4', '10', 'walter', '', '' ], [ 'blue', '4', '10', 'walter', '', '' ], [ 'red', '2', '15', 'smith', '+', '' ] ];

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)