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

Hi Monks, I have a script that GrandFather updated. I tried to add the uniq feature which will give only uniq lines. Here is the code-
use strict; use warnings; use 5.010; my @lists; my %group; my $lastGroup; while (defined(my $line = <DATA>)) { next if $line =~ /^access-list .*\bremark\b/; given ($line) { when (/^access-list/) { my @keys = $line =~ /([A-Z]+[-_][A-Z]+)/g; push @lists, {groups => \@keys, line => $line}; } when (/object-group\s+(\S+)\s+(\S+)/) { $group{$2}{line} = $line; $group{$2}{data} = []; $lastGroup = $2; } default { push @{$group{$lastGroup}{data}}, $line; push @{$group{$lastGroup}{groups}}, $1 if $line =~ /^\s+\S+\s+(\S+)$/; } } } # ------Uniq list--------------------- sub uniq { my %seen; grep !$seen{$_}++, @_; } my @lists1 = uniq(@lists); for my $list (@lists1) { print $list->{line}; printGroups($list->{groups}, %group); print "\n"; } # ------Uniq list--------------------- sub printGroups { my ($groups, %groupData) = @_; for my $group (sort @$groups) { next if !exists $groupData{$group}; print $groupData{$group}{line}; print @{$groupData{$group}{data}} if $groupData{$group}{data}; printGroups($groupData{$group}{groups}, %groupData) if exists $groupData{$group}{groups}; } } __DATA__ access-list INSIDE_IN remark DNS Client To DNS Server access-list INSIDE_IN extended permit tcp object-group DNS-CLIENT obje +ct-group DNS-SERVER object-group DNS_TCP access-list INSIDE_IN extended permit udp object-group DNS-CLIENT obje +ct-group DNS-SERVER object-group DNS_UDP object-group network PC1_1st network-object host 10.1.1.11 object-group network PC2_1st network-object host 10.1.1.12 object-group network DNS-CLIENT group-object PC1_1st group-object PC2_1st object-group network DNS-SERVER network-object host 10.1.1.5 object-group service DNS_TCP tcp port-object eq domain object-group service DNS_UDP udp port-object eq domain
But it's not printing uniq lines and skip if already exist above-

Output now-
access-list INSIDE_IN extended permit tcp object-group DNS-CLIENT obje +ct-group DNS-SERVER object-group DNS_TCP object-group network DNS-CLIENT group-object PC1_1st group-object PC2_1st object-group network PC1_1st network-object host 10.1.1.11 object-group network PC2_1st network-object host 10.1.1.12 object-group network DNS-SERVER network-object host 10.1.1.5 object-group service DNS_TCP tcp port-object eq domain access-list INSIDE_IN extended permit udp object-group DNS-CLIENT obje +ct-group DNS-SERVER object-group DNS_UDP object-group network DNS-CLIENT group-object PC1_1st group-object PC2_1st object-group network PC1_1st network-object host 10.1.1.11 object-group network PC2_1st network-object host 10.1.1.12 object-group network DNS-SERVER network-object host 10.1.1.5 object-group service DNS_UDP udp port-object eq domain
Output looking for
access-list INSIDE_IN extended permit tcp object-group DNS-CLIENT obje +ct-group DNS-SERVER object-group DNS_TCP object-group network DNS-CLIENT group-object PC1_1st group-object PC2_1st object-group network PC1_1st network-object host 10.1.1.11 object-group network PC2_1st network-object host 10.1.1.12 object-group network DNS-SERVER network-object host 10.1.1.5 object-group service DNS_TCP tcp port-object eq domain access-list INSIDE_IN extended permit udp object-group DNS-CLIENT obje +ct-group DNS-SERVER object-group DNS_UDP object-group service DNS_UDP udp port-object eq domain
Please let me know.

Replies are listed 'Best First'.
Re: Uniq list
by kennethk (Abbot) on Jul 12, 2016 at 14:11 UTC
    Or, phrased more diplomatically than morgon chose, please review How do I post a question effectively?. Note that we are here to help you debug your own work, not do it for you. What did you try? What did it do, and how was that different than what you expected?

    A very rudimentary filter to only print the first occurrence of a line in an output stream would be piping it through:

    perl -nE 'print if not $seen{$_}++'
    adapted from perlfaq4's How can I remove duplicate elements from a list or array?.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Uniq list
by Laurent_R (Canon) on Jul 12, 2016 at 14:01 UTC
    Hi,

    if I understand well, your @lists array contains hash references, not input lines. There is no hope that your uniq subroutine running on this array will remove duplicate lines from your data, if that's what you're after.

    Either you should rewrite the uniq subroutine to work on the lines nested inside the hash refs, or you should remove duplicate lines earlier in the process.

Re: Uniq list
by Marshall (Canon) on Jul 12, 2016 at 14:23 UTC
    I made some changes to printGroups to use same "seen trick". Won't print the same $groupData{$group}{line} twice. Could be some flaw here, but this is a quick way that looks like it produces the desired output.
    my %seen; ### sub printGroups { my ($groups, %groupData) = @_; for my $group (sort @$groups) { next if !exists $groupData{$group}; if (!$seen{$groupData{$group}{line}}++) ### { ### print $groupData{$group}{line}; print @{$groupData{$group}{data}} if $groupData{$group}{dat +a}; printGroups($groupData{$group}{groups}, %groupData) if exists $groupData{$group}{groups}; } ### } } =prints access-list INSIDE_IN extended permit tcp object-group DNS-CLIENT obje +ct-group DNS-SERVER object-group DNS_TCP object-group network DNS-CLIENT group-object PC1_1st group-object PC2_1st object-group network PC1_1st network-object host 10.1.1.11 object-group network PC2_1st network-object host 10.1.1.12 object-group network DNS-SERVER network-object host 10.1.1.5 object-group service DNS_TCP tcp port-object eq domain access-list INSIDE_IN extended permit udp object-group DNS-CLIENT obje +ct-group DNS-SERVER object-group DNS_UDP object-group service DNS_UDP udp port-object eq domain =cut
      It worked. Thank you.
Re: Uniq list
by morgon (Priest) on Jul 12, 2016 at 13:54 UTC
    You found the right place as PM is of course a free code writing service.

    For best results I would recommend setting a deadline.