For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > August 2004 > convertinga directory path into a hash









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author convertinga directory path into a hash
Zebee Johnstone

2004-08-24, 3:58 am


I have a unix directory path, say /home/user/mail

Not knowing how long it will be, that is, how many elements, how can I
convert it into a sequence of hashes:
$ref->{'home'}->{'user'}->{'mail'}

zebee

--
Zebee Johnstone (zebee@zip.com.au), proud holder of
aus.motorcycles Poser Permit #1.
"Motorcycles are like peanuts... who can stop at just one?"
Christian Winter

2004-08-24, 3:58 am

Zebee Johnstone schrieb:
> I have a unix directory path, say /home/user/mail
>
> Not knowing how long it will be, that is, how many elements, how can I
> convert it into a sequence of hashes:
> $ref->{'home'}->{'user'}->{'mail'}


You could use eval() for that, like:
----------------------------------------------------
#!perl

use strict;
use warnings;
use Data::Dumper;

sub hashify {
my $var;
my $p = shift;
$p =~ s#^/##; # remove leading slash
$p =~ s#/$##; # remove trailing slash
$p =~ s|/|"}->{"|g; # build hashref syntax
eval '$var->{"'.$p.'"}="somevalue"'; # ...and eval into $var
return $var; # which is returned
}

my $retval = hashify("/home/user/mail");

print Data::Dumper->Dump( [$retval] );

print $retval->{'home'}->{'user'}->{'mail'},$/;
------------------------------------------------------

HTH
-Christian
Zebee Johnstone

2004-08-24, 3:58 am

In comp.lang.perl.misc on Tue, 24 Aug 2004 08:43:56 +0200
Christian Winter <thepoet_nospam@arcor.de> wrote:
> Zebee Johnstone schrieb:
>
> You could use eval() for that, like:


Thanks! Now to see if the idea that this was a solution
to will work.

between asking and being answered I thought up another solution
but that isn't right, so back to this one.

Zebee
Tassilo v. Parseval

2004-08-24, 9:06 am

Also sprach Zebee Johnstone:

> I have a unix directory path, say /home/user/mail
>
> Not knowing how long it will be, that is, how many elements, how can I
> convert it into a sequence of hashes:
> $ref->{'home'}->{'user'}->{'mail'}


This can be done with a simple recursive function:

sub path2hash {
my ($p, $ref) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
path2hash($tail, $ref->{ $head } = {});
return $ref;
}

my $ref = path2hash("/home/user/mail");

Note that using string eval (as recommended elsewhere) looks tempting
for a task like this but it can be done just as well (and even more
safely) without.

Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{re
htonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
Zebee Johnstone

2004-08-24, 9:06 am

In comp.lang.perl.misc on Tue, 24 Aug 2004 09:57:17 +0200
Tassilo v. Parseval <tassilo.von.parseval@rwth-aachen.de> wrote:
> Also sprach Zebee Johnstone:
>
>
> This can be done with a simple recursive function:
>
> sub path2hash {
> my ($p, $ref) = @_;
> return if not $p;
> my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
> path2hash($tail, $ref->{ $head } = {});


I don't understand what you are passing here, and how the subroutine
sees it.
> return $ref;
> }
>
> my $ref = path2hash("/home/user/mail");
>
> Note that using string eval (as recommended elsewhere) looks tempting
> for a task like this but it can be done just as well (and even more
> safely) without.
>
> Tassilo



--
Zebee Johnstone (zebee@zip.com.au), proud holder of
aus.motorcycles Poser Permit #1.
"Motorcycles are like peanuts... who can stop at just one?"
Tassilo v. Parseval

2004-08-24, 9:06 am

Also sprach Zebee Johnstone:

> In comp.lang.perl.misc on Tue, 24 Aug 2004 09:57:17 +0200
> Tassilo v. Parseval <tassilo.von.parseval@rwth-aachen.de> wrote:
>
> I don't understand what you are passing here, and how the subroutine
> sees it.


It's a short-cut. More explicitely:

$ref->{ $head } = { };
path2hash($tail, $ref->{ $head });

In Perl, assignments have a return value and that was what I was using
here.

Other than that, it should be pretty straight-forward. Note that this is
a so called primitive recursion because each instantiation of the
function cuts off a piece of its argument ($head) and calls path2hash
with the thusly diminshed argument ($tail).

Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{re
htonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
Uri Guttman

2004-08-24, 4:40 pm

>>>>> "TvP" == Tassilo v Parseval <tassilo.von.parseval@rwth-aachen.de> writes:

TvP> Also sprach Zebee Johnstone:
[color=darkred]

TvP> sub path2hash {
TvP> my ($p, $ref) = @_;
TvP> return if not $p;
TvP> my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
TvP> path2hash($tail, $ref->{ $head } = {});
TvP> return $ref;
TvP> }

TvP> my $ref = path2hash("/home/user/mail");

TvP> Note that using string eval (as recommended elsewhere) looks tempting
TvP> for a task like this but it can be done just as well (and even more
TvP> safely) without.

and i wrote a non-recursive version a long while back in my tutorial on
autovivification:

http://sysarch.com/perl/autoviv.txt

look for deep_hash_assign. you would call it by first splitting the path
on / and passing it the list of dir name parts.

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
Brian McCauley

2004-08-24, 4:40 pm

> I have a unix directory path, say /home/user/mail

Since you don't say where I'll assume it's in $_

I'll also assume you can assume you've got a valid absolute path.

> Not knowing how long it will be, that is, how many elements, how can I
> convert it into a sequence of hashes:
> $ref->{'home'}->{'user'}->{'mail'}


Assming that $ref is initially undef and you want that node to be undef...

{
my $r = \$ref;
$r = \$$r->{$_} for /[^\/]+/g;
}

Anno Siegel

2004-08-25, 9:00 am

Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote in comp.lang.perl.misc:
> Also sprach Zebee Johnstone:
>
>
> It's a short-cut. More explicitely:
>
> $ref->{ $head } = { };
> path2hash($tail, $ref->{ $head });
>
> In Perl, assignments have a return value and that was what I was using
> here.
>
> Other than that, it should be pretty straight-forward. Note that this is
> a so called primitive recursion because each instantiation of the
> function cuts off a piece of its argument ($head) and calls path2hash
> with the thusly diminshed argument ($tail).


That means that recursion can be replaced with a jump to the
subroutine. Untested:

sub path2hash {
my ($p, $ref) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
@_ = ( $tail, $ref->{ $head} = {});
goto &path2hash;

"goto &..." is (among other things) Perl's method to cut off tail
recursion.

Anno
Tassilo v. Parseval

2004-08-25, 3:57 pm

Also sprach Anno Siegel:

> Tassilo v. Parseval <tassilo.parseval@post.rwth-aachen.de> wrote in comp.lang.perl.misc:


>
> That means that recursion can be replaced with a jump to the
> subroutine. Untested:
>
> sub path2hash {
> my ($p, $ref) = @_;
> return if not $p;
> my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
> @_ = ( $tail, $ref->{ $head} = {});
> goto &path2hash;
>
> "goto &..." is (among other things) Perl's method to cut off tail
> recursion.


If it had been proper tail recursion, yes. Note that by doing it this
way, you loose the ability to return the populated hash-reference and
you have to do a call-by-reference (sort of). In context, this will
become:

sub path2hash {
my ($p) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
@_ = ($tail, $_[1]->{ $head } = {});
goto &path2hash;
}

path2hash("/home/user/mail", my $ref);

Tassilo
--
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{re
htonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com