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

Hey,

This program is supposed to take a last name, a comma, and a first name(in that order) and print the first name followed by the last. It works great, I was just wondering if my program was efficent; I want to see if there's some neat tricks I'm overlooking. Thanks.

open(TEST, 'test.txt') || die "Couldn't open it"; $i=1; while(<TEST>){ ($lname[$i], $fname[$i]) = split(','); $i+=1; } close(TEST); open(BTEST, '>test.txt'); $b=0; foreach (@fname) { chomp; print BTEST "$_ $lname[$b]\n"; $b+=1; } close(BTEST);

-Emmitt

Replies are listed 'Best First'.
Re: Refining my Program
by Kanji (Parson) on May 24, 2002 at 22:58 UTC
    I want to see some if there's neat some tricks I'm overlooking.

    Oh, most definitely!

    By making use of Perl's command-line/#!switches, you can turn your script into a one-liner...

    perl -aF, -pli -e '$_ = "@F[1,0]"' test.txt

    ...although you may need to supply an argument to -i and change the quotes (ie, ' for ", and qq() for ') on OSes like Windows.

    perl -aF, -pli.bak -e "$_ = qq(@F[1,0])" test.txt

        --k.


    Update: Flipping " to ' won't work because of interpolation, so you really need something like qq() instead. Oops.

    Update 2: Added explanation for the curious...

      OK, this definitely gets a ++ from me. I sort of understand how each switch operates by itself, but when I try to put them all together for this one-liner, my brain explodes. So, can anyone give a step-by-step explanation of this thing? Thanks.

      --

      There are 10 kinds of people -- those that understand binary, and those that don't.

Re: Refining my Program
by cLive ;-) (Prior) on May 24, 2002 at 23:10 UTC

    timtowtdi - and you should have checked you could open to write! ;-)

    #!/usr/bin/perl -w use strict; my $output; open(TEST, 'test.txt') || die "Couldn't open it"; while (<TEST>) { chomp; $output .= sprintf("%s %s\n", (split /,/)[1,0] ) ; } close(TEST); open(TEST, '>test.txt') || die "Couldn't open it"; print TEST $output; close(TEST);

    (s)printf tutorial here.

    cLive ;-)

    --
    seek(JOB,$$LA,0);

Re: Refining my Program
by DamnDirtyApe (Curate) on May 24, 2002 at 22:33 UTC

    Here's how I'd handle that:

    use strict ; open( TEST, 'test.txt' ) || die "Couldn't open it"; my @names = () ; while ( <TEST> ) { chomp ; my ( $lname, $fname ) = split /,/ ; push @names, $fname, $lname ; } close( TEST ) ; open( BTEST, '>test.txt' ) ; while ( @names ) { my ( $fname, $lname ) = splice @names, 0, 2 ; print BTEST "$fname $lname\n" ; } close( BTEST ) ;

    Update: Fixed capitalization on print statement. Doh!


    _______________
    D a m n D i r t y A p e
    Home Node | Email
Re: Refining my Program
by Anonymous Monk on May 24, 2002 at 23:00 UTC
    On Unix:
    perl -pi.bak -e 's/(.*),(.*)/$2 $1/' test.txt
    Windows uses " instead of '.

    Beyond that, have an indentation style, check $! on open, and it usually winds up being a bad idea to edit files in place - leave the original and write a copy. (Or at least keep a backup as I did above.)

Re: Refining my Program
by Anonymous Monk on May 25, 2002 at 20:51 UTC
    Since I am not the best at one liners, I would have done it: <meta name="Generator" content="Vim/6.0"> </head> <body bgcolor="#000000" text="#ffffff">
    use struct;
    
    my $first;
    my $last;
    
    open  (INPUT,'>test.txt') || die "Can't open Test.txt";
    open (OUTPUT, '<testb.txt') || die "Can't open Testb.txt";
    while (<INPUT>){
        ($last,$first)=split(',');
        print OUTPUT "$first , $last";
    }
    close INPUT;
    close OUTPUT;
    
    </body> </html>