![]() |
|
|
|
|
|||||||
| Forums | Portal | Register | Forum Rules | FAQ | Contribute | Members List | Arcade | Search | Today's Posts | Mark Forums Read |
| Shell Programming and Scripting Post questions about KSH, CSH, SH, BASH, PERL, PHP, SED, AWK and OTHER shell scripts here. |
|
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| How ls | wc -l works? | krishmaths | UNIX for Dummies Questions & Answers | 3 | 04-11-2008 01:16 PM |
| Help it works but its to SLOW | Garlandxj | Shell Programming and Scripting | 10 | 04-03-2008 12:17 AM |
| Works with FTP but not NFS | pbonilla | UNIX for Dummies Questions & Answers | 1 | 01-08-2008 02:31 PM |
| How the for loop works? | neelaksh | UNIX for Dummies Questions & Answers | 6 | 02-04-2007 10:42 AM |
| how it works hosts | jgutierrez29 | UNIX for Dummies Questions & Answers | 1 | 06-08-2005 01:37 PM |
|
|
Submit Tools | LinkBack | Thread Tools | Search this Thread | Display Modes |
|
#1
|
|||
|
|||
|
Still trying to get a grep -c that works
I am trying to get a count of each line
sub runit2 { my ($file1a, $file2a) = @_; my $file1_vala = $file1a->get; my $file2_vala = $file2a->get; open (FILE1a, "$file1_vala") or die; open (FILE2a, "$file2_vala") or die; chomp(my @strings = <FILE2a>); while (1) { foreach $pattern (<FILE1a>) { chomp($pattern); last if $pattern =~ /^\s*$/; my @matches = eval { grep $pattern eq $_, @strings; }; if ($@) { print "Error: $@"; } else { my $count = @matches; print "$count $pattern \n", #$text->insert('end', "$count $pattern $_\n"); } } return; } 1 ip routing 1 ip classless 1 no ip bootp server 1 no ip http server 1 no ip http secure-server 1 ip bgp-community new-format 1 no access-list 23 1 no access-list 51 1 logging buffered 4096 debugging 1 banner motd ^ 6 ************************************************* 6************************************************** 2 ^ 1 banner exec ^ 6************************************************** 2 * LEGAL NOTICE * 6 *************************************************** 6 *************************************************** 2 * LEGAL NOTICE * 6 **************************************************** 2 ^ 1 ip dhcp excluded-address 10.8.26.1 10.8.26.100 1 ip dhcp excluded-address 10.8.26.200 10.8.26.254 1 no auto-summary 1 snmp-server view BLOCK iso included 1 snmp-server view BLOCK ipAddrEntry.*.*.*.*.* included 1 snmp-server view BLOCK ipAddrEntry.*.10.*.*.* excluded 1 snmp-server view BLOCK ipNetToMediaEntry.*.*.*.*.*.* included 1 snmp-server view BLOCK ipNetToMediaEntry.*.*.10.*.*.* excluded 1 snmp-server view BLOCK atEntry.*.*.*.*.*.*.* included 1 snmp-server view BLOCK atEntry.*.*.*.10.*.*.* excluded 2 snmp-server ifindex persist 2 snmp-server enable traps snmp authentication linkdown linkup coldstart warmstart 1 snmp-server enable traps frame-relay 1 snmp-server enable traps frame-relay subif 1 snmp-server enable traps config 1 ip tacacs source-interface loopback0 1 snmp-server trap-source loopback0 1 ip flow-export source fa0/0 1 ip flow-export version 5 origin-as 1 ip flow-export destination 10.15.1.2 9996 1 ip flow-cache timeout active 1 1 ip flow-cache timeout inactive 15 2 snmp-server ifindex persist 1 logging trap notifications 1 logging source-interface fa0/0 2 snmp-server enable traps snmp authentication linkdown linkup coldstart warmstart 1 privilege exec level 1 traceroute 1 privilege exec level 1 ping 1 privilege exec level 1 show configuration 1 line con 0 2 exec-timeout 5 0 3 login 1 line aux 0 2 exec-timeout 5 0 3 login 1 line vty 0 4 1 exec-timeout 30 0 1 no privilege level 15 1 no access-class 23 in 3 login 1 end The easiest thing to look at is the 3 login lines. login appears in file 2 3 times. I only want a single output of "3 login" and not that statement every time the script encounters login. |
| Forum Sponsor | ||
|
|
|
#2
|
|||
|
|||
|
You still want to drop the eval. Trust me on this, it's not doing anything useful.
Save the matches to a hash and print it only at the end. One of the earlier threads where you asked about this had a solution which did that. Code:
foreach $pattern (<FILE1a>) {
chomp($pattern);
last if $pattern =~ /^\s*$/;
my $matches = grep $pattern eq $_, @strings;
++$count{$pattern} if $matches;
}
for my $key (keys %count) {
print "$count{$key} $key\n";
}
|
|
#3
|
|||
|
|||
|
Here is the exact sub that I now have in the script
#*********************** sub runit2 { my ($file1a, $file2a) = @_; my $file1_vala = $file1a->get; my $file2_vala = $file2a->get; open (FILE1a, "$file1_vala") or die; open (FILE2a, "$file2_vala") or die; $text->insert('end', "Device config contains: \n"); chomp(my @strings = <FILE2a>); while (1) { foreach $pattern (<FILE1a>) { chomp($pattern); last if $pattern =~ /^\s*$/; my @matches = eval { #grep /$pattern/, @strings; grep $pattern eq $_, @strings }; if ($@) { print "Error: $@"; } else { my $count = @matches; $text->insert('end', "$count $pattern \n"); } } return; } close FILE1a; close FILE2a; } If I take out the infinite while loop, the output is "Device config contains: 1 no service tcp-small-servers" Thats it, no further iteration. If I leave it in, a snip of the output which is really not desirable ... . . . . . 2 snmp-server enable traps snmp authentication linkdown linkup coldstart warmstart 1 snmp-server enable traps frame-relay 1 snmp-server enable traps frame-relay subif 1 snmp-server enable traps config 1 ip tacacs source-interface loopback0 1 snmp-server trap-source loopback0 1 ip flow-export source fa0/0 1 ip flow-export version 5 origin-as 1 ip flow-export destination 10.15.1.2 9996 1 ip flow-cache timeout active 1 1 ip flow-cache timeout inactive 15 2 snmp-server ifindex persist 1 logging trap notifications 1 logging source-interface fa0/0 2 snmp-server enable traps snmp authentication linkdown linkup coldstart warmstart 1 privilege exec level 1 traceroute 1 privilege exec level 1 ping 1 privilege exec level 1 show configuration 1 line con 0 2 exec-timeout 5 0 3 login 1 line aux 0 2 exec-timeout 5 0 3 login 1 line vty 0 4 1 exec-timeout 30 0 1 no privilege level 15 1 no access-class 23 in 3 login 1 end If I modify the code above to #*********************** sub runit2 { my ($file1a, $file2a) = @_; my $file1_vala = $file1a->get; my $file2_vala = $file2a->get; open (FILE1a, "$file1_vala") or die; open (FILE2a, "$file2_vala") or die; $text->insert('end', "Device config contains: \n"); #******************************* foreach $pattern (<FILE1a>) { chomp($pattern); last if $pattern =~ /^\s*$/; my $matches = grep $pattern eq $_, @strings; ++$count{$pattern} if $matches; } for my $key (keys %count) { print "$count{$key} $key\n"; } #******************************* close FILE1a; close FILE2a; } I would expect the hash to be printed in the "dos" window. If the following is included, I get very many errors. use strict %count = (); If omitted, nothing is printed to the dos window, but it does run. |
|
#4
|
|||
|
|||
|
Sorry ...
This line is also included in sub .. chomp(my @strings = <FILE2a>); Hosed my cut and paste. |
|
#5
|
|||
|
|||
|
When you use strict, all of your code needs to be strict. It's a hassle at first but it's useful when you start getting useful warnings when the code doesn't do what you expect. If your code is not strict, tackle that later. But adopt it in the next script you write. It's good for you.
The last will quit the foreach loop on the first blank or empty line. If you have empty lines in the patterns file, you probably mean "next", not "last". If you have the same pattern multiple times in the pattern file, you will get multiple prints of the count of matches. I was under the impression that you were getting 1 login 2 login 3 login but now I see that you have 3 login 3 login 3 login, so it's simply reporting the same pattern multiple times. Welp, you can use a hash to prevent that, too. Code:
sub runit2 {
my ($file1a, $file2a) = @_;
my $file1_vala = $file1a->get;
my $file2_vala = $file2a->get;
open (FILE1a, "$file1_vala") or die;
open (FILE2a, "$file2_vala") or die;
chomp(my @strings = <FILE2a>);
close FILE2a;
$text->insert('end', "Device config contains: \n");
#*******************************
foreach $pattern (<FILE1a>) {
next if $pattern =~ /^\s*$/;
next if $handled{$pattern};
$handled{$pattern} = 1;
chomp($pattern);
my $matches = grep $pattern eq $_, @strings;
next unless $matches;
$text->insert('end', "$matches $pattern \n");
}
close FILE1a;
}
Last edited by era; 04-22-2008 at 01:55 PM. Reason: Optimize so $handled goes before grep |
|||
| Google The UNIX and Linux Forums |