File Coverage

blib/lib/App/RecordStream/Operation/grep.pm
Criterion Covered Total %
statement 61 65 93.8
branch 17 18 94.4
condition 3 3 100.0
subroutine 8 9 88.8
pod 0 5 0.0
total 89 100 89.0


line stmt bran cond sub pod time code
1             package App::RecordStream::Operation::grep;
2              
3             our $VERSION = "4.0.25";
4              
5 3     3   765 use strict;
  3         6  
  3         69  
6              
7 3     3   12 use base qw(App::RecordStream::Operation);
  3         4  
  3         200  
8              
9 3     3   277 use App::RecordStream::Executor::Getopt;
  3         4  
  3         50  
10 3     3   11 use App::RecordStream::Executor;
  3         4  
  3         1170  
11              
12             sub init {
13 5     5 0 5 my $this = shift;
14 5         6 my $args = shift;
15              
16 5         6 my $anti_match;
17 5         14 my $context = 0;
18 5         7 my $after = 0;
19 5         6 my $before = 0;
20 5         24 my $executor_options = App::RecordStream::Executor::Getopt->new();
21 5         10 my $spec = {
22             "-v" => \$anti_match,
23             "C=s" => \$context,
24             "A=s" => \$after,
25             "B=s" => \$before,
26             $executor_options->arguments(),
27             };
28              
29 5         22 $this->parse_options($args, $spec, ['bundling']);
30              
31 5         14 my $expression = $executor_options->get_string($args);
32 5         21 my $executor = App::RecordStream::Executor->new($expression);
33              
34 5         7 $this->{'ANTI_MATCH'} = $anti_match;
35              
36 5 100       10 if ( $context ) {
37 1         2 $after = $before = $context;
38             }
39              
40 5         6 $this->{'AFTER'} = $after;
41 5         6 $this->{'BEFORE'} = $before;
42              
43 5         10 $this->{'ACCUMULATOR'} = [];
44              
45 5         64 $this->{'EXECUTOR'} = $executor;
46             }
47              
48             sub accept_record {
49 25     25 0 26 my $this = shift;
50 25         23 my $record = shift;
51              
52 25         29 my $executor = $this->{'EXECUTOR'};
53 25         41 my $result = $executor->execute_code($record);
54              
55 25 100       42 $result = not $result if ( $this->{'ANTI_MATCH'} );
56 25         38 my $pushed_record = 0;
57              
58 25 100       68 if ( $result ) {
    100          
59 8 100       16 if ( $this->{'BEFORE'} ) {
60 2         4 while(my $record = shift @{$this->{'ACCUMULATOR'}}) {
  4         15  
61 2         5 $this->push_record($record);
62             }
63             }
64              
65 8         50 $this->push_record($record);
66 8         9 $pushed_record = 1;
67 8         17 $this->{'SEEN_RECORD'} = 1;
68              
69 8 100       25 if ( $this->{AFTER} > 0 ) {
70 2         3 $this->{'FORCED_OUTPUT'} = $this->{'AFTER'};
71             }
72             }
73             elsif ( $this->{'BEFORE'} > 0 ) {
74 8         9 push @{$this->{'ACCUMULATOR'}}, $record;
  8         13  
75              
76 8 100       10 if ( (scalar @{$this->{'ACCUMULATOR'}}) > $this->{'BEFORE'} ) {
  8         14  
77 4         5 shift @{$this->{'ACCUMULATOR'}};
  4         7  
78             }
79             }
80              
81 25 100 100     49 if ( $this->{'FORCED_OUTPUT'} && (! $pushed_record) ) {
82 2         5 $this->push_record($record);
83 2         3 $this->{'FORCED_OUTPUT'}--;
84             }
85              
86 25         72 return 1;
87             }
88              
89             sub stream_done {
90 5     5 0 6 my $this = shift;
91 5 50       8 $this->_set_exit_value(1) unless ( $this->{'SEEN_RECORD'} );
92             }
93              
94             sub add_help_types {
95 5     5 0 8 my $this = shift;
96 5         14 $this->use_help_type('keyspecs');
97 5         8 $this->use_help_type('snippet');
98             }
99              
100             sub usage {
101 0     0 0   my $this = shift;
102              
103 0           my $options = [
104             App::RecordStream::Executor::options_help(),
105             ['v', 'Anti-match. Records NOT matching will be returned'],
106             ['C NUM', 'Provide NUM records of context around matches, equivalent to -A NUM and -B NUM'],
107             ['A NUM', 'Print out NUM following records after a match'],
108             ['B NUM', 'Print out the previous NUM records on a match'],
109             ];
110              
111 0           my $args_string = $this->options_string($options);
112              
113 0           return <
114             Usage: recs-grep []
115             __FORMAT_TEXT__
116             is evaluated as perl on each record of input (or records from
117             ) with \$r set to a App::RecordStream::Record object and \$line set to the current
118             line number (starting at 1). Records for which the evaluation is a perl
119             true are printed back out.
120             __FORMAT_TEXT__
121              
122             Arguments:
123             $args_string
124              
125             Examples:
126             Filter to records with field 'name' equal to 'John'
127             recs-grep '\$r->{name} eq "John"'
128             Find fields without ppid = 3456
129             recs-grep -v '{{ppid}} == 3456'
130             Filter to records with all methods equal to 'PUT'
131             recs-grep -MList::MoreUtils=all 'all { \$_ eq 'PUT' } \@{\$r->{methods}}'
132             USAGE
133             }
134              
135             1;