LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   awk help (https://www.linuxquestions.org/questions/programming-9/awk-help-592130/)

uttam_h 10-16-2007 12:33 AM

awk help
 
hi all,
i have a log file with following content

<req>
<op>login</op>
<succ>0</succ>
</req>
<req>
<op>login</op>
<succ>1</succ>
</req>
<req>
<op>logout</op>
<succ>0</succ>
</req>
<req>
<op>delete</op>
<succ>0</succ>
</req>
<req>
<op>message</op>
<succ>0</succ>
</req>
..............
.............
...............
..............

i want to count the op parameters(eg. login, logout....) for which succ is 0 using awk

Regards,
uttam hoode

ghostdog74 10-16-2007 01:38 AM

Code:

awk '{ last=line;line=$0;}
    /<succ>0<\/succ>/ { gsub(/<op>|<\/op>/,"",last) ; store[last]++}
    END{ for(i in store) print store[i],i}' "file"


bigearsbilly 10-16-2007 02:47 AM

grep -c '<succ>0</succ>'

Tinkster 10-16-2007 03:40 AM

Quote:

Originally Posted by bigearsbilly (Post 2925789)
grep -c '<succ>0</succ>'

That'll count ALL successes, and not split them up
in login/logout, which is -if I understood the request
correctly - what the OP asked forl; it will count
messages and other ops, too.



Cheers,
Tink

Tinkster 10-16-2007 03:53 AM

And a slightly different approach...
Code:

awk 'BEGIN{RS="/req>";FS="\n"}/succ>0/{if($0~/op>login/){login++};if($0~/op>logout/){logout++}} END{print login" "logout}' log


Cheers,
Tink

radoulov 10-16-2007 04:22 AM

... and another one:

Code:

awk '$2=="op"{k=$3;x[k];next}
$2=="succ"&&$3==0{x[k]++}END{
for(i in x)print i,x[i]+0}' FS="[<>]" file


uttam_h 10-16-2007 04:42 AM

hi all,
Thanks for the solutions.
Regards,
uttam hoode

AnanthaP 10-16-2007 07:23 AM

If ( "<succ>0</succ>" )
<fail>1</fail> ;

OP <Quote>i want to count the op parameters(eg. login, logout....) for which succ is 0 using awk</Unquote>

bigearsbilly 10-16-2007 08:08 AM

oops, sorry tink

is this understandable?

Code:

#!/usr/bin/perl

local $/ = undef; # slurp mode

@L = split /<req>/, <ARGV>;
@L = grep /login/, @L;
@L = grep />0</, @L;

print scalar @L, "\n";
#  print "@L";


matthewg42 10-16-2007 10:32 AM

Your input looks something like XML, although I think it needs to all be inside a single document tag to be valid. If you are parsing XML, it might be wise to use a proper parsing library - you never know if one day your input file will be reformatted like this:
Code:

<req>
<op>
login
</op>
<succ>
0
</succ>
</req>

...which will break the suggestions above. The rules of computing say this will happen at the worst possible time and cause you a lot of grief.

Parsing XML properly is a little more complicated that using the pattern based approaches above, but it is more reliable.
Code:

#!/usr/bin/perl

use warnings;
use strict;

use XML::XPath;
use XML::XPath::XMLParser;

# read in all files specified on command line, or data from standard input
# into the variable $xml_source.  Since the input isn't valid (there can be
# only one base tag in an XML document), we will enclose the whole lot it
# in <doc> tags.
my $xml_source = "<doc>\n";
while (<>) { $xml_source .= $_; }
$xml_source .= "</doc>\n";

# This will be used to count occurrances of the various <op> sections.
my %counters;

# Now create a parser object which looks at $xml_source
my $xp = XML::XPath->new(xml => $xml_source);

# find all req/op tags
my $nodeset = $xp->find("/doc/req/op");

# for each op tag count the contents.
foreach my $node ($nodeset->get_nodelist) {
        addcount($node->string_value);
}

# output the results.
foreach my $key (keys %counters) {
        printf("%-3d %s\n", $counters{$key}, $key);
}

# Since we are using warnings, we cannot use an undefined value and assume
# it will be 0, so we whck and if it is already defined incremement it, else
# set the value to 1.
sub addcount {
        my $key = shift || return;
        if ( defined($counters{$key}) ) { $counters{$key}++; }
        else { $counters{$key} = 1; }
}



All times are GMT -5. The time now is 05:35 PM.