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

Here is the final code. Thank you everyone!
print"\n"; print "Please enter file name and path:"; chomp($filename = <STDIN>); #Gets File to Search print "File Name: $filename"; #Prints the File Name print "\n"; #Skips Line open DAFILE, "$filename"; #Opens the file to Search open(testfile,"Hints.txt") or die "Can't find file\n"; #Opens Hints.tx +t $i=0; #Var array counter @daarray = (); #Var Array while(<testfile>){ #While Hints.txt file is open $daarray[$i] = $_; #Loads each line of Hints.txt into array $i++; # array's index } close(testfile); #Close Hints.txt while(<DAFILE>) #While the File is Open { $input = $_; #Get next line of the file for($j=0; $j<=$i; $j++) #for each item in array { ($first,$last) = split(/\ == /,$daarray[$j]); #Split Hints.txt + line if($input =~ m/$first/i) {printf "Found: %s\r", $last;} } } print "Search Complete\n"; #Print close DAFILE; #close DAFILE

Replies are listed 'Best First'.
Re: Search Script
by Roy Johnson (Monsignor) on May 04, 2005 at 16:36 UTC
    What you're doing now is reading the entire DAFILE while you're on the first line of HintsFile. You would need to re-open DAFILE (or seek to the beginning) on each pass through the loop to search it again. Of course, that's not really recommended.

    What you should probably do is read all of one file or the other (whichever is expected to be smaller) into an array, and then use a foreach loop to walk through that array each time you read a line from the (other) file.


    Caution: Contents may have been coded under pressure.
      Roy thank you for replying. The below script is what I think you were saying.
      print"\n"; print "Please enter file name and path:"; chomp($filename = <STDIN>); print "File Name: $filename"; print "\n"; open DAFILE, "$filename"; open (HintsFile, "Hints.txt") or die "Can't find file\n"; #$input = <DAFILE>; $hints = <HintsFile>; open(testfile,"Hints.txt"); $i=0; @daarray = (); while(<testfile>){ $daarray[$i] = $_; $i++; } close(testfile); for($j=0; $j<$i; $j++) { $hints = $daarray[$j]; ($first,$last) = split(/\ == /,$hints); if($first =~ m/$input/i) {print "Found: $last"; print "\n"; } } print "Search Complete\n"; close DAFILE; close HintsFile;
      Thank you very much for the advice! I'm still having some issues with the search, any thoughts? arebc
        You've got a lot of clutter in there. You are opening Hints.txt in two places, for example. You need to clearly understand what you want the computer to do, and in what order. Then code that. It might help for you to write out the steps in English (or other language of your choice) in comments first. Then under each step, write the code to perform that step. You might find that the code almost writes itself, then.

        You have a lot of pieces that are more or less what you will want to use, but you haven't got them put together right. In particular, it doesn't look like you're reading DAFILE any more. You need to have a read-loop for that, surrounding the for-$j loop, so that the j loop is executed for every line read from DAFILE.


        Caution: Contents may have been coded under pressure.
Re: Search Script
by davidrw (Prior) on May 04, 2005 at 16:48 UTC
    Can you comment a little more on your use of $first and $last (for example, why is it printing $last after matching $first)?

    Also, it seems to me like your intent (note variable order/placement) for the regex is to have something like:
    if( $input =~ /$first/i ){ ... }

    The first solution to come to mind for this is to leverage the 'strings' and 'grep' shell commands.. perhaps something like (and hopefully someone will post a pure-perl 'strings' equivalent--the 'grep' of course could be done in perl):
    # prompt for $filename open HINTS, "Hints.txt" or die "Can't find file\n"; while( my $hintline = <HINTS> ){ my ($first,$last) = split(/\ == /,$hints); my $results = `strings $filename | grep -i '$first'`; next unless length $results; printf "Found: %s\n", $last; } close HINTS;
    This will also avoid binary-file issues, which i'm sure will be mentioned in other comments.
      Hello David, Thank you very much for your ideas. The next time I post anything I will make sure to comment my code, I apologize for that. I changed the structure of the code, do you think I could still use the
      while( my $hintline = <HINTS> ){ my ($first,$last) = split(/\ == /,$hints); my $results = `strings $filename | grep -i '$first'`; next unless length $results; printf "Found: %s\n", $last;
      for the search. What is the "my" used for? Sorry I'm new to Perl.
        The "my" is used to declare variables (see eibwen's post).

        You should also include this:
        use strict; use warnings;
        at the top of your scripts -- what these will do is enforce (or warn) about certain things that will save you lots of trouble in the long-run, and point out compiling problems. Check out the manpages for each ("man strict", "man warnings") for more details. Something it is especially useful for is enforcing variable declarations:
        This will run, but NOT do what you want:
        $myvariable = 3; print "Pi is exactly $myvaraible";
        This code, however, will give a very informative error message if you try to run it:
        use strict; my $myvariable = 3; print "Pi is exactly $myvaraible";

        Consult perlfunc, which contains the following for my:

        While I still don't understand why you return $last if $first is found, I think you may be looking for a hash:

        #!/usr/bin/perl -w use strict; my %hints; open FILE, 'hints'; while (<FILE>) { chomp; my @hint = split(/\s*==\s*/); $hints{$hint[0]} = $hint[1]; } close FILE; my $filename = 'file'; open FILE, $filename; binmode FILE; { local $/; my $file = <FILE>; print map { $file =~ /$_/ ? $hints{$_} : () } keys %hints; } close FILE;

        Granted the above code is likely slower than using `strings | grep`, but it illustrates that this can be done in pure perl.