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
|
|
|
|
|