pattern 1: 1=2 2=3 0=-1 pattern 2: 1=2 3=4 pattern 3: 3=4 5=2 #### # PART 1: Per-column pattern-matching values # when this column ... # has this value ... # count it as a column match toward these pats ... 0 => { -1 => [ 'pattern 1' ] }, 1 => { 2 => [ 'pattern 1', 'pattern 2' ] }, 2 => { 3 => [ 'pattern 1' ] }, 3 => { 4 => [ 'pattern 2', 'pattern 3' ] }, 5 => { 2 => [ 'pattern 3' ] } # PART 2: Pattern sizes # this pattern ... # requires this many column matches ... 'pattern 1' => 3, 'pattern 2' => 2, 'pattern 3' => 2 #### my %pattern_colvals; my %pattern_sizes; # convert pattern specs into internal representation while () { my ($pattern, $spec) = split /:\s*/, $_, 2; my @col_patterns = map [split /=/], split ' ', $spec; $pattern_sizes{$pattern} = @col_patterns; for (@col_patterns) { my ($col, $match_val) = @$_; push @{$pattern_colvals{$col}{$match_val}}, $pattern; } } #### # parse input CSV file and check for matches against patterns while (<>) { chomp; my @col_vals = split /,/; # use real CSV parsing instead my ($col, %col_matches); for (@col_vals) { for (@{ $pattern_colvals{$col++}{$_} }) { print "line $. matches $_$/" if ++$col_matches{$_} == $pattern_sizes{$_}; } } } #### $ { echo -1,2,3,4,5,6 echo -1,2,4,0,0,9 echo 0,0,0,4,3,2 } | perl pm-patterns.pl line 1 matches pattern 1 line 1 matches pattern 2 line 3 matches pattern 3