2013-03-07 4 views
0

Y at-il une fonction f dire (dans la base Perl ou une bibliothèque) tel que:concaténation annuaire Perl

f("https://stackoverflow.com/a/b/c", "./d") == "https://stackoverflow.com/a/b/c/d" 
f("https://stackoverflow.com/a/b/c", "../d") == "https://stackoverflow.com/a/b/d" 
f("https://stackoverflow.com/a/b/c", "/d") == "/d" 

Fondamentalement, il renvoie le répertoire qui résulterait de façon répétée cd ing.

+0

Vous pouvez écrire votre propre! –

+1

Nul s'il y en a un intégré, mais ce serait facile d'en faire un. : P '$ pwd = $ ENV {PWD}; chdir $ path1; chdir $ path2; $ resultat = $ ENV {PWD}; chdir $ pwd; ' – cHao

+0

duplication possible de [http://stackoverflow.com/questions/6579495/how-to-concatenate-pathname-and-relative-pathname](http://stackoverflow.com/questions/6579495/how -to-concatenate-pathname-et-relative-pathname) – uba

Répondre

7

de base de File::Spec a une telle fonction (rel2abs), mais je préfère Path::Class (parce qu'il est trop facile à utiliser File :: Spec correctement).

use Path::Class qw(dir); 
say dir('./d')->absolute('/a/b/c'); # /a/b/c/d 
say dir('../d')->absolute('/a/b/c'); # /a/b/d 
say dir('/d')->absolute('/a/b/c');  # /d 

Utilisation file au lieu de dir si vous créez un chemin vers un fichier. Par ailleurs, ./d est juste une façon verbeuse d'écrire d.


Oops, sur les systèmes unix, qui retourne /a/b/c/../d pour celui du milieu, car il est impossible de savoir /a/b/c/../d signifie /a/b/d sans vérifier le système de fichiers. (En fait, il peut s'agir de /a/b/e/f/d.) Je ne connais aucun outil permettant de tracer des chemins absolus en vérifiant le système de fichiers à l'aide d'une base autre que pwd.

+0

Voir la note ajoutée pour répondre. – ikegami

0

probablement ce manque beaucoup de choses, mais une fonction f peut ressembler à ceci:

use warnings; 
use strict; 

sub f { 
    my ($s, $cd) = @_; 
    return $cd if ($cd =~ m!^/!); # return path if abs 
    $cd =~ s!//+!/!g; 
    my @v = split(/\//, $cd); 
    my @i = split(/\//, $s); 
    for my $c (@v) { 
    next if $c eq "."; 
    pop @i, next if $c eq ".."; 
    push @i, $c; 
    } 
    return join("/", @i); 
} 

my @p = ( 
    ["https://stackoverflow.com/a/b/c", "./d"], 
    ["a/b/c", "../d"], 
    ["https://stackoverflow.com/a/b/c/", "/d"], 
    ["a/b/c/e/f/g", "../../c/e/../d"]); 

print f(@$_), "\n" for @p;