use strict; use warnings; use List::Util qw/reduce/; sub _extract { my @names = @_; my @pairs; # create all xor'd pairs for(my $i=0; $i<@names; $i++) { for (my $j=$i+1; $j<@names; $j++) { push @pairs, $names[$i] ^ $names[$j]; } } no warnings 'once'; my $or = reduce { $a | $b } @pairs; if ( $or =~ /\0+/ ) { my $index = $-[0]; my $length = $+[0] - $-[0]; return substr $names[0], $index, $length; } else { # match not successful, so return undef return; } } sub extract_tag { my @names = @_; my $tag; $tag = _extract(@names); # try matching with reversed @names # this finds common substrs at the end $tag = reverse _extract(map {scalar reverse $_} @names) unless defined $tag; return $tag; } my @names; local $, = ':'; local $\ = "\n"; while () { chomp; print(extract_tag(@names)), @names = (), next unless /\S/; push @names, $_; } print extract_tag(@names); __DATA__ jP|Azrael jP|Blade jP|Henry Jeff.ocr pr!me.ocr Lokren.ocr woRUTtan hiRUTfango biRUTff salTAGo blasTAGi RipTAGu