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

Hi Monks , Can you see the problem with my script , I am trying to add information about students age inside a file as follow:
--- DATA ---- NAME AGE Sue 22 Sam 34 LUi 43
My script works fine and update the file , however , I don't want to add a duplicte entries in the file so if Sue 22 exists I don't want to add it again , I am checking for that in my script but it is not catching it .
$|++; use strict; use Fcntl ':flock'; print "Enter new student's name: "; chomp( my $student = <STDIN> ); print "Enter new student's number: "; chomp( my $studentAge = <STDIN> ); open my $fh, '+<', 'students.dat' or die "open failed: $!"; flock $fh, LOCK_EX or die "flock failed: $!"; my $found = 0; while (<$fh>) { $found = 1 if /^\Q$student\E$/i; } print $fh $student ,"\t" , $studentAge ,"\n" unless $found; close $fh;
Ok thanks

Replies are listed 'Best First'.
Re: regex issue
by matija (Priest) on Feb 27, 2004 at 21:03 UTC
    Your file contains the name and the age on each line.

    However, since you anchor the search with the ^ at the start and the $ at the end, and you're only looking for the name, it can't match.

    You could match with /^\Q$student\E\s+\d+$/ - Student name, one or more blanks, one or more digits.

      using the index work but it only checks for the name , I am trying to see if the age match as well, I will skip that line only if the name and age match. thanks
        Well, then, you need to match on both the name and the age:
        $found = 1 if /^\s*\Q$student\E\s+\Q$studentAge\E\s*$/
        should do the trick. If no one else ever touches the file, you can get away with eliminating with \s* on either side, but I figure they don't hurt, on the off chance someone brings the data file into an editor at some point.
Re: regex issue
by TomDLux (Vicar) on Feb 28, 2004 at 02:13 UTC

    The string/regex you compare to should encompass as much as possible of the whole output string:

    # need to chomp the file input before testing $found = 1 if /^$student\t$studentAge$/;

    Personally, I would suggest using eq because this isn't really a regex problem. You are searching the file for an exact match to a string which is completely known. A regex might be suitable if you were looking for, say, a name followed by an age: /^\s*\w+\s+\d+\s*$. But testing for string equality fits what you are doing, and is faster than a regex.

    my $text = "$student\t $studentAge\n"; my $found = 0; while (<$fh>) { $found = 1 if $_ eq $text; }

    Your example here deals with the input of a single name and age. If you're dealing with homework, that might be all you need. Or, if you're writing a web interface to soemthing, you'll obtain your information one at a time. In other cases, however, you would receive many names, many ages. In that case, I would suggest reading the file into a hash, so you can quickly and easily test each new value.

    # Read the file into a hash # my %dataFileContains; open my $fh, 'students.dat' or die "open failed: $!"; my $line; while ($line = <$fh>) { chomp $line; $dataFileContains{$line}++; } close $fh; # # Read in and test each value, caching those which # will be output. # my @output; my ( $name, $age ); while ( ($name, $age ) = getStudentData() ) { my $outLine = "$name\t$age"; push @output, $outLine unless $dataFileContains{$outLine}; } # # Output the data. # if ( scalar @output ) { open my $fh, '>>students.dat' or die "open failed: $!"; foreach ( @output ) { print $fh, "$output\n"; } }

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: regex issue
by injunjoel (Priest) on Feb 27, 2004 at 21:50 UTC
    Greetings all,
    Sounds to me like a job for grep...
Re: regex issue
by esskar (Deacon) on Feb 27, 2004 at 20:54 UTC
    well this is nor really speedy
    my $found = 0; while (<$fh>) { $found = 1 if index($_, $student) == 0; }
      There's a problem with your code: It will give a false positive if you have a name which is identical to part of a shorter name

      (for instance: John Smith would match, even though the name in the file is John Smithers).

      what did you do :)) , What does the index function do ? thanks
      Hummmmmmmm , doesn't work my friend!!!! prints duplicate entries.