问题
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