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

Hello monks,

dumb question, but I am trying to change the following grep:

my @tags = split /\t/, $line; my @Definition=("NN", "NNS"); next unless (grep {$_ eq $tags[ 1 ]} @Definition);

in order that it matches only at the beginning of the string. I thought that the following would do it, but I was wrong...:

next unless grep($_ =~ /^$tags[1]/, @Definition);

Replies are listed 'Best First'.
Re: grep beginning of string (updated)
by haukex (Archbishop) on Dec 12, 2018 at 17:46 UTC

    Works for me...

    use warnings; use strict; use Data::Dumper; my $line = "X\tN"; my @tags = split /\t/, $line; my @Definition=("A", "NN", "B", "NNS", "YN", "ZX"); my @out = grep($_ =~ /^$tags[1]/, @Definition); print Dumper(\@out); __END__ $VAR1 = [ 'NN', 'NNS' ];

    Could you show an SSCCE where it fails for you? Just an idea, you might want to check for stray whitespace in @tags (see Basic debugging checklist).

    By the way, the match against $_ is implicit, and you probably want to use \Q...\E to have regex metacharacters match literally (see e.g. Mind the meta!). Also, I prefer the {BLOCK} form of grep - I would have written grep {/^\Q$tags[1]\E/} @Definition.

    Minor ninja edits.

    Update: If you instead mean that you want to check if $tags[1] begins with one of the strings in @Definition, then one way to do that is described in Building Regex Alternations Dynamically:

    use warnings; use strict; use Data::Dumper; my @Definition=("NN", "NNS"); my ($defs) = map { qr/$_/ } join '|', map {quotemeta} sort { length $b <=> length $a } @Definition; for my $str ( "ABC", "NXY", "NNF", "NNSX" ) { print "$str: ", $str=~/^$defs/ ? "yes!\n" : "no\n"; } __END__ ABC: no NXY: no NNF: yes! NNSX: yes!

    (Although ("NN", "NNS") is kind of redundant, ("NN") is enough.)

Re: grep beginning of string
by thanos1983 (Parson) on Dec 13, 2018 at 09:10 UTC

    Hello IB2017,

    As fellow Monk haukex said, if the string that you want to compare have the same root e.g. NN or NNS (same root NN) then you can use:

    #!/usr/bin/perl use strict; use warnings; sub check { return substr($_[0], 0, length($_[1])) eq $_[1]; } foreach my $string ("ABC", "NXY", "NNF", "NNSX") { print "$string: ", check($string, "NN") ? "yes!\n" : "no\n"; } __END__ $ perl test.pl ABC: no NXY: no NNF: yes! NNSX: yes!

    Should be faster than grep you can Benchmark the codes.

    Update: Removing unnecessary sample of code.

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!