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

O Wise ones,

I am a summer intern, and my first perl script is to write a script that will open a dat file and move through it string be string commenting it out and writing each seperate instance to another dat file. So edit1.dat would have "$Blue Car Green" and edit2.dat would have "Blue $Car Green", etc... :

Here is what I have:

#!usr/bin/perl use File::Copy; print "What file would you like to edit? \n"; chomp($editfile = <>); copy($editfile, "edit.dat") || die "Cannot copy file: $!"; open(INFO,"edit.dat") || die "Can't open edit.dat: $!"; $header = <INFO>; undef $/; $sequence = <INFO>; my @twodarray = split(' ',$sequence); $list[0] = \@twodarray; $x=1; for ($j=0; $j<=$#{$list[0]}; $j++) { for ($k=0; $k<=$#list; $k++) { copy("edit".$x.".dat", "edit.dat"); open(OTHER, ">edit$x.dat"); seek OTHER, 0 ,0; $position = $list[$k][$j]; $commentout = "\$"; $commentout = $commentout .= $position; s/$position/$commentout/; print OTHER; $x++; } print "\n"; } close INFO;

Well it creates the files, but they are all empty. But I checked the $position and $commentout variables, and they hold the right values. I'm a noob to the ways of perl, so any help would be greatly appreciated. Thanks.

"theintern"

20070621 Janitored by Corion: Added formatting, code tags, as per Writeup Formatting Tips

Replies are listed 'Best First'.
Re: Opening a file, editing, copying to another
by Grundle (Scribe) on Jun 20, 2007 at 21:55 UTC
    Your files are empty becuase you are printing nothing to them.

    In your loop you have
    $commentout = $commentout .= $position; s/$position/$commentout/; print OTHER; #THIS LINE HERE!! $x++;
    That line does nothing. If you want to write to your file you would do
    print OTHER "I am printing foo to file\n";
    another thing that should be pointed out

    s/$position/$commentout/
    This does nothing. Are you trying to do a regular expresion with that? If so you need to go back and read up on the Perl regular expressions. It should have the form
    $variable =~ s/<regular-expression>/<substitution-here>/; #For example the following my $variable = "Blue Car"; print $variable."\n"; $variable =~ s/Blue/Red/; print $variable."\n";
    I hope that helps

    p.s. For better posting encapsulate your scripts inside the
    <code>
    tags.
      That line does nothing. If you want to write to your file you would do

      Actually, no. Consider:

      $_ = "HW"; s/HW/Hello World/; print STDOUT;

      Prints:

      Hello World

      You perhaps need to learn about $_? See $ARG/$_ in perlvar.


      DWIM is Perl's answer to Gödel
        Just to be extremely explict, "print STDOUT;" is the same as "print STDOUT $_;". Both of these statements print the value of the special Perl variable, $_, to STDOUT. Similarly, "print OTHER;", which is the same as "print OTHER $_;", prints the value of $_ to the "OTHER" file.
        Ahh ++ I wasn't aware of that. That seems to be a sloppy way of doing things in my mind, even though it is a quicker shorthand.

        In any case I do not see where $_ is ever being set. Running the code myself it comes up empty for every iteration. The data that he wants to operate on is stored in his 2-D Array $list[][]. It makes complete sense that nothing is sent to his files because $_ is empty.

        Thanks for pointing out my mistake ;) Although I know about $_ I rarely use it. I find it more readable to explicitely name my variables, and it aids in maintainability for future changes.
Re: Opening a file, editing, copying to another
by GrandFather (Saint) on Jun 21, 2007 at 14:39 UTC

    Without trying to figure out what you are actually trying to achieve with the file manipulation, here at least is a sample the does what you seem to want for the line manipulations:

    use strict; use warnings; my @lines = map {[split]} <DATA>; for my $line (@lines) { for my $wordIndex (0 .. $#$line) { substr $line->[$wordIndex], 0, 0, '$'; print join (' ', @$line), "\n"; substr $line->[$wordIndex], 0, 1, ''; } print "\n"; } __DATA__ one fish, two fish, red fish, blue fish

    Prints:

    $one fish, one $fish, $two fish, two $fish, $red fish, blue fish red $fish, blue fish red fish, $blue fish red fish, blue $fish

    Note in particular the use of strictures (use strict; use warnings;) and the use of Perlish for loops rather than C for loops.

    Note too that for sample code it is useful if the code can be run with sample data provided - a __DATA__ section helps a lot with that.


    DWIM is Perl's answer to Gödel