use strict; use warnings; my ($d, $k1, $k2, $k3); while () { chomp; @_ = split /\:/; push @{$d->{$_[0]}{$_[1]}{$_[2]}}, $_[3]; } for $k1 (keys %$d) { for $k2 (keys %{$d->{$k1}}) { for $k3 (keys %{$d->{$k1}{$k2}}) { for (@{$d->{$k1}{$k2}{$k3}}) { print "$k1:$k2:$k3:$_\n"; } } } } __DATA__ category1:category2:category3:options categorya:categoryb:categoryc:more options categoryd:categorye:categoryf:even more options