#!/usr/bin/perl use strict; use warnings; use Data::Dumper; $Data::Dumper::Useqq = 1; $| = 1; my @sorted_cols = ( 2, 0, 1, 3 ); my %conwithposition = ( TITLE => [ 0, 'ne', [ 'Lord', 'Senator' ] ], HANDLE => [ 2, 'eq', [ 'BeginR' ] ], ); # TITLE, FIRST_NAME, HANDLE, LAST_NAME my @lines = ( "Mr.\tNice\tBeginR\tPerson", "Senator\tNice\tBeginR\tPerson", "Mr.\tBruce\tUtil\tGray", ); # The %conwithposition hash does not *have* to be a hash, # and would be easier to work with if it was an array. # The "values to match" variable can be a scalar # or an arrayref; not only to we have to determine which # it is and handle it differently every time it is used, # we also cannot directly match against an array; # it would be better in hash form. # Transform from a HoA # where the type of last element varies between scalar and arrayref # $field_name => [ $field_position, $operator, $value or \@values ] # to an AoA # where the last element is always a hash. # [ $field_name, $field_position, $operator, \%values_to_match ] my @conditions_with_position = map { my $field_name = $_; my ( $field_position, $operator, $value_to_match ) = @{ $conwithposition{$_} }; my $type = ref $value_to_match; my @values = ( $type eq '' ) ? ( $value_to_match ) : ( $type eq 'SCALAR' ) ? ( ${ $value_to_match } ) : ( $type eq 'ARRAY' ) ? ( @{ $value_to_match } ) : die "Unexpected type '$type'" ; my %val_hash = map { $_ => 1 } @values; [ $field_name, $field_position, $operator, \%val_hash ]; } keys %conwithposition; my @checked_lines_AoA = map { [ @{$_}[@sorted_cols] ] } grep { matches_all_fields( $_, \@conditions_with_position ) } map { [ split "\t", $_ ] } @lines; print Dumper \@checked_lines_AoA; sub matches_all_fields { my ( $line_aref, $conditions_aref ) = @_; foreach my $condition( @{ $conditions_aref } ) { my ($field_name, $field_pos, $op, $vals_href) = @{$condition}; my $field = $line_aref->[$field_pos]; return if not matches_one_field( $field, $op, $vals_href ); } return 1; } sub matches_one_field { my ( $line_field, $operator, $vals_to_match_href ) = @_; my $match = $vals_to_match_href->{$line_field}; my $op_match = ( $operator eq 'eq' ) ? $match : ( $operator eq 'ne' ) ? !$match : die "Unknown op '$operator'" ; return $op_match; }