use strict; use Data::Dumper; my (%hash,@queue); while () { chomp; if (/^#DEFINE\s+<([^>]+)>\s+(.*)/) { $hash{$1} = $2; } } do_it($_) for keys %hash; do_it(shift @queue) while @queue; sub do_it { my $key = shift; $hash{$key} =~ s/<([^>]+)>/$hash{$1}/g; unshift @queue, $key if $hash{$key} =~ / /path/to/something #DEFINE v12 #DEFINE 3 #DEFINE /foo_.txt #### #DEFINE v12