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

I have a text file generated with file names that have already printed. I am trying to loop through the .txt file and if I see a file name, don't do anything. However, with the way I have it written, if ANY file shows up, nothing prints (print to another .dat file). How do I control the loop through the PARTS text file? Here's my code snip:

$partlist = "D:\\scripts\\partlist.txt"; #get the parts that have already been printed open(PARTS, $partlist) || die "Can't open file: $!"; @PARTS= <PARTS>; close(PARTS); #set counter $found = 0; foreach $PARTS(@PARTS) { if ($PARTS == $ordnum) { $found=1; }} if ($found eq 0){ $verifile = $outbox.$ordnum.".dat"; ##Open output file to write to open(OUTPUT_FILE, ">>$verifile")||die "Can't open file: $!"; print OUTPUT_FILE $these.$happy.$variables close OUTPUT_FILE; else { #nothing }

I know my logic is a little off, but can't seem to iron it out. Any thoughts?

update:
$partlist contains, for example, the text printfileA, I am going out to a DB getting an order number and then bringing back in with a hash... if the result of the order is printfileA.dat then it should not print since it's already been printed as indicated by $partlist. However, if my DB results show printfileA.dat and then printfileB.dat, printfileB.dat never gets created because the script stopped once it saw printfileA.dat. Sorry if I haven't been clear enough.

-Hu

Edit: g0n - code tags

Replies are listed 'Best First'.
Re: Looping through a file
by almut (Canon) on Apr 15, 2008 at 20:18 UTC

    Unless $PARTS and $ordnum are both numbers, you probably want to compare them using

    if ($PARTS eq $ordnum) { ...

    (eq is for comparing strings, such as "printfileA")

    Similarly, as $found seems to be used in a boolean fashion (0=false/1=true), it would suffice to say

    unless ($found) { ...

    (Not sure if that helps, but other than that, I can't say much, because even after having read your post twice, I'm still not quite sure what exactly you need to do...  — but as always, that could also be due to a problem on my side ;)

Re: Looping through a file
by pc88mxer (Vicar) on Apr 15, 2008 at 20:19 UTC
    What does $ordnum look like? Does it look like a number or does it contain non-numeric characters? If the latter, you'll want to use a string comparison here:
    if ($PARTS eq $ordnum) {
    Also, note that the elements of the @PARTS array will have the terminating newline at the end, and this will interfere with string comparisons. To get rid of that, you can use:
    chomp(@PARTS = <PARTS>);
    Frankly, my preference is use a read loop:
    while (<PARTS>) { chomp; if ($_ eq $ordnum) { ...
    And finally, you can make your search a little more efficient by short-circuiting the loop when you've found a match:
    for $PARTS (@PARTS) { if ($PARTS eq $ordnum) { # assuming 'eq' is correct here $found = 1; last; } }
      Thank you! Yes, there will alphanumeric, so I will use "eq" instead of "==".

      And yes, it's an array, not a hash as I seemed to indicate. Doy!

      If/when I figure it out, I'll post complete code for future reference.

      -Hu
Re: Looping through a file
by Erez (Priest) on Apr 15, 2008 at 20:21 UTC

    Three pointers,
    first, put

    use strict; use warnings;

    at the top of your file. That would point out any jarring issue you have in your code (also surround your code here with <code></code> tags).
    Declare your variables with my and run it again.

    Two, say open(my $PARTS, '<', $partlist) and while (<$PARTS>) to better arrange your file handling.

    Third, 0 is Perl's false state (among others) so unless ($found) would do (also, numeric equal is ==, not eq so you need to say $found == 0 and $PARTS eq $ordnum).

    Try these and see what errors you pick up.

    As for your code itself, you run through the entire @parts, then check on the state of $found. If $found is a counter (as you say in the comments, say $found++. If its an indicator, you need to do something when you locate a file.

    Software speaks in tongues of man.
    Stop saying 'script'. Stop saying 'line-noise'.
    We have nothing to lose but our metaphors.

Re: Looping through a file
by toolic (Bishop) on Apr 15, 2008 at 20:28 UTC
    Your question is not clear enough for me. It would be useful if I could run your code to try to reproduce your results, but the code does not compile. Try to reduce your code to be a stand-alone script, and provide a small sample of what your input file contains. Refer to GrandFather's excellent node: I know what I mean. Why don't you?.

    I suspect you have the comparison operators confused. To compare numeric values, use ==; to compare strings, use eq.

    You probably want to change:

    if ($found eq 0){

    to:

    if ($found == 0){

    If you are trying to compare 2 strings here, use eq:

    if ($PARTS == $ordnum) {
Re: Looping through a file
by apl (Monsignor) on Apr 15, 2008 at 20:23 UTC
    What have you done to track the path of code executed during your test?

    What's $ordnum supposed to be?

    If the contents of the Parts file are text, why are you doing a numeric equivalence test?

    Where's use strict; use warnings;?

    I know my logic is a little off, but can't seem to iron it out.
    Write pseudo-code. Say your answer in English to your room-mate. How would you resolve the problem manually?
      I have a print request from a database query I just ran. I'd like to check to see if I've already printed this request. Previo +us requests are in a .txt file. Open the text file and read in all the prior print jobs. If the print request from the database query is in the text file, skip + it. If the print request from the database query is not in the text file, +create a new .dat file for printing.
        First, you want to load the contents of <PARTS> into a hash, not an array.

        Then, you test for the existence of the database query in the hash. If it's not already defined, create the new file.

        How would you implement these two pieces?