use warnings; use strict; sub two_d_search{ my $amount_of_data = shift; my @data = splice @_, 0, $amount_of_data; my @pattern = (); my ($arg, $indentation, $string); my $i = 0; while (@_){ $arg = shift; if ($arg eq "\n"){ $i++; $arg = shift; } $indentation = $arg; $string = shift; $pattern[ $i ] .= ".{$indentation}" if $indentation; $pattern[ $i ] .= $string; print "($i: $pattern[ $i ])", "\n"; } my $pos; my $match = 0; my @matches = (); for my $i (0 .. @data - 1){ undef pos $data[ $i ]; OUT_2: while ($data[ $i ] =~ m/$pattern[0]/g){ ($pos) = @-; # matches can overlap, so 'pos' increases only by +1: (pos $data[ $i ]) = $pos + 1; for my $j (1 .. @pattern - 1){ pos ($data[ $i + $j ]) = $pos; if ($data[ $i + $j ] =~ m/\G$pattern[$j]/){ # do nothing } else { next OUT_2 } } $match ++; push @matches, "[row: $i|column: $pos]"; } } $" = "\n"; # set list output separator to "\n" return "Number of matches: $match;", "Upper-left corners match at:\n@matches" } my @data = ; chomp @data; my @info = &two_d_search( scalar @data, @data, # indentation; string; argument of line separation 1, '#', "\n", # two_d_regex first line 0, '#', "\n", # two_d_regex second line 2, '#\.' # two_d_regex third line ); print "@info",$/; __DATA__ #..#.....#. ..#...##... .#....#..## #..#....#.. ..#...#..#. .......#.#. ...........