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

Hello Monks, How do I greo for exact word in n array? for now I have this as foreach $ARGV ( @ARGV ) { $exists = grep (/$ARGV/, @serv) } I am not able to grep for exact word.

Replies are listed 'Best First'.
Re: grep exact words
by revdiablo (Prior) on Jun 25, 2004 at 23:00 UTC

    You can do it with a regex, by anchoring to the beginning and end of string, and quoting any metacharacters, like so:

    grep /^\Q$ARGV\E$/, @serv;

    Or, how I would do it, with eq:

    grep $_ eq $ARGV, @serv;
Re: grep exact words
by saskaqueer (Friar) on Jun 25, 2004 at 23:01 UTC

    When using grep(), you are iterating over each item in the list (in this case @serv). An alias to the item is made on each pass, which is stored in $_ for you. Your example does a simple pattern match against $ARGV, so let's just change that to do an equality test:

    #!perl -w use strict; my @serv = qw(foo bar baz); for my $arg (@ARGV) { # exact match (foo/foo match, but not foo/Foo) my $valid_arg = grep { $arg eq $_ } @serv; # case insensitive (foo/foo match, so do foo/Foo) # my $valid_arg = grep { lc($arg) eq $_ } @serv; die("Invalid argument '$arg'.\n") unless ($valid_arg); }

      This is the code I have used and its not working....am I missing some syntax here?

      open (FILE, "<$list") or die "$list failed: $!\n"; @srvr = <FILE>; close (FILE); foreach $ARGV ( @ARGV ) { #$exists = grep { $ARGV eq $_ } @srvr; if (!$exists) { print "Cant do this"; # exit (1); } }

      20040626 Edit by Corion: Added CODE tags

        You've probably still got line endings ("\n") on the values in @srvr. See perldoc -f chomp.

        Do you know you have the exists line commented out?

        We're not really tightening our belts, it just feels that way because we're getting fatter.
        open (FILE, "<$list") or die "$list failed: $!\n"; chomp(@srvr = <FILE>); #note close (FILE); foreach $ARGV ( @ARGV ) { print "Comparing <$ARGV> to\n"; $exists = grep { print " <$_>\n"; $ARGV eq $_ } @srvr; if (!$exists) { print "Cant do this"; # exit (1); } }

        We're not really tightening our belts, it just feels that way because we're getting fatter.
      Hello , For some reason the code isnt working.... Actually I am reading the @serv from a text file and comparing the ARGV to the values in the text file. I dunno where the error is coming up.
Re: grep exact words
by Roy Johnson (Monsignor) on Jun 26, 2004 at 12:53 UTC
    Because you're searching the same list multiple times, you should probably do this:
    my %seen = map { $_ => 1 } @serv; foreach $ARGV (@ARGV) { if (!$seen{$ARGV}) { warn "$ARGV not found\n" next; } # Whatever you want to do when found }

    We're not really tightening our belts, it just feels that way because we're getting fatter.
      I tried the code you posted..it doesnt seem to be working . What is this 1 in the code here:- my %seen = map { $_ => 1 } @serv;
        %seen is a hash. map is constructing a list of key-value pairs to assign to it. Each element of @serv is a key, and 1 is the value for each. It's the same as saying
        my %seen; @seen{@serv} = (1) x @serv;
        Saying "doesn't seem to be working" is not useful. Providing your input, output, and what you expected to be different could help.

        Please do note the advice to chomp the lines you're reading from a file. "foo\n" will not be equal to "foo".


        We're not really tightening our belts, it just feels that way because we're getting fatter.
Re: grep exact words
by andyf (Pilgrim) on Jun 26, 2004 at 19:14 UTC

    Here's another take. It looks like you want to read an argument list for a program. It also looks like you are just using the file as a temporary test method to develop the prog, as I have followed in the example below. But you are possibly making life too complicated for yourself using a list to store what will in reality be a string of values or flags. When you come to use this code for real, to get arguments replace <FILE> with @ARGV at line 7. Alternatively, try using getopt::Std.

    #!/usr/bin/perl my $list = './argslist'; # test file of args my @argstomatch = ('--hack','--and','--pray','--elephants'); my $srvr; open (FILE, "<$list") or die "open $list failed: $!\n"; for(<FILE>){$srvr .= $_}; # append all lines together close (FILE); # at this point we are done collecting - everything is + in one $srvr string # the rest demonstrates index for $argfindme(@argstomatch) { printf ("%s\t%s\n", $argfindme, index($srvr,$argfindme)); }

    You will see a number next to each argument in the @argstomatch list. This is -1 if the argument doesn't exist, otherwise it's the position of the first character of the match in $srvr.

      Hello noble people, Thank you kindly for all your answers....but since I am short of time...I have found an alternative method to get around this... for ($i = 0; $i <= $#ARGV; $i++) { $gname = `grep -w @ARGV$i $server_list`; if ( length($gname) == 0) { print "ERROR: Bad input to the script\n"; } This seems to work for now.