#!perl -w my @data = ; for my $test ( # ( "olive&(popeye|bluto)", "(tom&jerry)|(sylvester&tweety)", "moe&(shemp|curly|joe)&larry", "moe curly larry", # "&" is optional "moe&!curly&larry", # curly not present "moe ( shemp | curly | joe ) larry", # "|" is required "jerry -tom", # standard way of "AND" and "AND NOT"... "(moe)((shemp)|(curly)|(joe))(larry)", # also this "tom&jerry|sylvester&tweety", # use re's default precedence "moe(&shemp|curly|joe)&larry", # error: "(&" instead of "&(" "moe ( shemp | curly | joe", # error: missing ")" "moe ) curly ( larry", # invalid: bad grouping "(olive)&(popeye|(bluto|brutus)))", # error: extra ")" "(jerry)((tweety))( )", # error: empty group "jerry||tweety", # error: empty word "olive - (bluto | brutus)", # only words can be excluded "olive - bluto - brutus", # Ok, spaces ignored. "(curly|!larry)&!moe", # valid, but senseless OR "moe&!(!curly)&larry", # error: curly present? "tom -!jerry" # error: don't try... # )[(shift)-1] ) { print "\n\n$test\n::\n"; (print("ERROR: Invalid expression\n") , next) if $test =~ /[^a-z\s\&\|\(\)\!\-]|^\s*[\&\|]|[\&\|]\s*$|[\&\|\(]\s*[\&\|\)]|[\!\-]\s*[^a-z\s]/; # not_valid_chars |op_begins | op_ends | no_consecutive_ops| negated_operator my $pars = $test; my $i = 0; $i++ while $pars =~ s/\((.*?)\)/$1/; (print("ERROR: Unpaired $1 of other $i pairs found\n") , next) if $pars =~ /([\(\)])/; my $expr = $test; $expr =~ s/([!\-]?)\s*(\w+)/($1?"(?!":"(?=").".*\\b$2\\b)"/ge; $expr =~ s/[\&\s]//g; $expr = "^($expr)"; print "$expr\n::\n"; print grep /$expr/, @data; } __DATA__ tom,jerry jerry,tom jerry,tomas sylvester,tweety tweeter,sylvester tom,sylvester popeye,olive olive,brutus moe,larry shemp,curly,joe larry,moe larry,curly,moe