trevdro trevdro - 5 months ago 9
Perl Question

Looking to search for string in text file



I'm learning some code and I want to run a subs routine that searches a file. If the name is present I want it to print the name. If the name is not present I want it to print not found. However the problem I am having is that it is printing found when the text is found but not found as so

Not found
found Trevor
Not found
Not found
Not found
found Trevor


What I want is the names printed when found but I do not want the not found presented. Likewise when the string is not present I want just one not found printed. I realise the problem is my while loop and if else statements. But I cannot find an arrangement that works the I want it to. Here is my current code;

sub search(){
open(FILE, "list.txt");
print("\n Search for subscriber\n\n");
my $search = <STDIN>;
while ($line = <FILE>){
if ( $line =~ /$search/) { print "found $search\n" }

else {
print("Not found \n");





Edit



The Perl code looks like this. Yes, it is unbalanced by three closing braces

sub search() {

open( FILE, "list.txt" );

print("\n Search for subscriber\n\n");
my $search = <STDIN>;

while ( $line = <FILE> ) {

if ( $line =~ /$search/ ) {
print "found $search\n";
}
else {
print("Not found \n");

Answer

As far as I understand your Q you want to print only once whether a given string, e.g. 'Trevor', is contained in your input file. This is similar to the shell command grep Trevor list.txt (or grep -q).

@toolic and @borodin already told about chomp(). It strips off the trailing \n character from your input ($search) and is needed because else you are really searching for Trevor\n which would only match at the end of a file's line.

If you only want to print once then simply add a (boolean) variable, iterate over the file (without printing) and finally print according to the flag. Once the string is found you can stop iterating. This is was the last; in the while loop does: it leaves the loop. Further iterations wouldn't change the result, so we can skip them.

There are -- as always in Perl -- many other possibilities to accomplish your task but I tried to stick as close as possible to your attempt.

Putting it together:

#!/usr/bin/env perl

use strict;
use warnings;

sub search
{
    print("\n Search for subscriber\n\n");
    my $search = <STDIN>;
    chomp($search);

    my $found = 0;
    open( my $fh, '<', 'list.txt' ) or die "cannot open list.txt: $!\n";
    while ( my $line = <$fh> ) {
        if ( $line =~ /$search/ ) {
            $found = 1;
            last;
        }
    }
    close($fh);

    if ($found) {
        print "found $search\n";
    } else {
        print "Not found\n";
    }
}