Perl set counter to match in loop

馋奶兔 提交于 2019-12-13 23:57:20

问题


How can I set a $counter++ to hash unless is 1? in this code:

use strict;
    use warnings;    

    my @filestwo = glob("*.xml");
    my $result = @filestwo;          

    my $count = 0;
    my %justone;
    foreach my $domain (@filestwo) {
      open my $in, '<', $domain or die "Open fail on $domain $!\n";
        my @linestwo = <$in>;        

            for my $line (@linestwo) {

                if($line =~ /Domain:\s([a-z].+)/){
                  $count++;
                  print "Number:$count Your TLD $1!\n" unless $justone{$1}++;
                }                

            }

}

The output:

Number:1 Your TLD one.com!
Number:3 Your TLD three.com!
Number:5 Your TLD two.com!

Should be:

Number:1 Your TLD one.com!
Number:2 Your TLD three.com!
Number:3 Your TLD two.com!

Explanation about the code:

  • Open 3 files .xml (In every file exist duplicate pattern)
  • Create a hash %justone;
  • Search from the array if the match the pattern: domain
  • If match and in the next iteration match again the same pattern, just print 1 with unless $justone{$1}++;

My problem, I can't set a counter just for the match relation unless hash.


回答1:


If you only want to increment unless some condition is met, you should mention that in your code.

Using the postfix foo() unless condition(); syntax means the condition will only refer to the previous statement, not the entire scope ( which would arguably be insane to parse ).

So print '...' unless $foo is the same as unless( $foo ){ print '...'; }.

Thus, if you want to include more than one statement in your unless condition, you need to use curly braces: unless ( $foo ) { # as many lines as desired }

If I understood your question correctly, you want to do:

unless ( $justone{$1}++ ){
    $count++;
    print "Number:$count Your TLD $1!\n"
}

This will increment only if the condition was met, and lead to the desired output. I would suggest to use a named variable for what you've captured in $1 to make it more readable, though.




回答2:


The problem is that $count++ should only be done once per domain like the print, which means you could simply move $count++ into the unless's body.

Alternatively, you could simplify your code by using

my %seen;
my @uniq_domains =
   grep !$seen{$_}++,
      map /Domain:\s([a-z].+)/,
         <$in>;

or

use List::Util qw( uniq );

my @uniq_domains =
   uniq
      map /Domain:\s([a-z].+)/,
         <$in>;

Then, the following outputs what you want:

say sprintf "%d. %s", $_+1, $uniq_domains[$_]
   for 0..$#uniq_domains;


来源:https://stackoverflow.com/questions/45390249/perl-set-counter-to-match-in-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!