#!/usr/bin/perl use strict; use warnings; my $csv_file="@ARGV"; my %struct_hash; ##### functions sub read_csv { my @csv; open my $fh, "$csv_file" or die "bad file: \"$csv_file\" - can't open\n"; push(@csv, "$_") while(<$fh>); close $fh; return @csv; }; ## builds %struct_hash with following inside: ## `$struct_hash{$_}->{'str'}` is utf8 string decr ## `$struct_hash{$_}->{'parent'}` full parent addrress ## `$struct_hash{$_}->{'plen'} = $len_par;` parent's length # ## here we go first with initializing $struct_hash and adding 'str' sub build_struct_hash { my %struct_hash; foreach(read_csv()) { my($pos_xy, $pos_str) = split(/;/, "$_"); $pos_xy =~ s/\D//g; $pos_str =~ s/\r//g; chomp($pos_str); $struct_hash{$pos_xy} = {}; $struct_hash{$pos_xy}->{'str'} = $pos_str; }; ## now we sort hash and creating length indexes 'plen' and 'parent' my $len_last = 0; my $len_par = 0; my $len_tmp = 2; foreach(sort {$a <=> $b} keys(%struct_hash)) { if(length == $len_tmp) { $struct_hash{$_}->{'parent'} = substr($_, 0, $len_par); $struct_hash{$_}->{'plen'} = $len_par; } else { $struct_hash{$_}->{'parent'} = substr($_, 0, $len_tmp); $struct_hash{$_}->{'plen'} = $len_tmp; $len_par = $len_tmp; }; $len_tmp = length; }; return %struct_hash; }; ########### main body: %struct_hash = build_struct_hash(); ########## user body: ## example # for work with all keys we need to do it like this: foreach(sort {$a <=> $b} keys(%struct_hash)) { print "$_ ", length; print "\t\t$struct_hash{$_}->{'parent'} $struct_hash{$_}->{'plen'}\t\t$struct_hash{$_}->{'str'}\n"; }; exit;