Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Help with Regular Expressions

by FFSparky (Acolyte)
on Apr 10, 2012 at 18:25 UTC ( #964383=perlquestion: print w/replies, xml ) Need Help??
FFSparky has asked for the wisdom of the Perl Monks concerning the following question:

Oh wise ones,

I have 2 string variables (these will be dynamic) containing file system paths. As labeled one string ($BasePath) will contain the base / root path and the other string ($CurrentPath) will be the current path as the script is scanning the file system starting from the base path. What I am after is a string containing just the subdirectory without the base / root path.

Using the working example I have provided the result is what I am after \DirD\DirE

However, I am rather weak with regular expressions thus to me my solution seems to be rough and naturally only deals with the dreaded windows paths. I am hoping there may be a more efficient alternative that could be dynamic and also support unix paths.

use strict; my $BasePath = '\\DirA\DirB\DirC'; my $CurrentPath = '\\DirA\DirB\DirC\DirD\DirE'; $BasePath =~ s/\x5c/\x0d/g; $CurrentPath =~ s/\x5c/\x0d/g; $CurrentPath =~ s/$BasePath//; $CurrentPath =~ s/\x0d/\x5c/g; print "\n\$CurrentPath: ".$CurrentPath."\n";

Thanks in advance.

Replies are listed 'Best First'.
Re: Help with Regular Expressions
by Riales (Hermit) on Apr 10, 2012 at 19:03 UTC

    There is a great CPAN module for this sort of thing: File::Spec.

    Specifically, it sounds like you want abs2rel:

    use File::Spec; my $rel_path = File::Spec->abs2rel($CurrentPath, $BasePath);

    Or were you trying to avoid using it for some reason or other?



      I was not aware of that module / abs2rel works just fine and I will now be using it.

      However I was hoping for a regular expression solution as I don't believe mine is the best and want to broaden my understanding use of these.

Re: Help with Regular Expressions
by johngg (Abbot) on Apr 10, 2012 at 22:18 UTC

    Part of the difficulty might be that even inside single quotes (or quoting construct as here) the backslash is a tricky customer.

    knoppix@Microknoppix:~$ perl -E ' > $bp = q{\\dirA\dirB\dirC}; > say $bp;' \dirA\dirB\dirC knoppix@Microknoppix:~$ perl -E ' $bp = q{\\\dirA\dirB\dirC}; say $bp;' \\dirA\dirB\dirC knoppix@Microknoppix:~$ perl -E ' $bp = q{\\\\dirA\dirB\dirC}; say $bp;' \\dirA\dirB\dirC knoppix@Microknoppix:~$ perl -E ' $bp = q{\\\\dirA\\dirB\\dirC}; say $bp;' \\dirA\dirB\dirC knoppix@Microknoppix:~$

    Riales has given you the best method but, just to show another way, you could split the paths rather than substituting the backslashes and shift off the common elements before joining what's left to get the relative path.

    knoppix@Microknoppix:~$ perl -E ' > $bp = q{\\\\dirA\\dirB\\dirC}; > say $bp; > $cp = q{\\\\dirA\\dirB\\dirC\\dirD\\dirE}; > say $cp; > @bpParts = split m{\\}, $bp; > @cpParts = split m{\\}, $cp; > do { shift @bpParts; shift @cpParts } while @bpParts; > $rp = join q{\\}, @cpParts; > say $rp;' \\dirA\dirB\dirC \\dirA\dirB\dirC\dirD\dirE dirD\dirE knoppix@Microknoppix:~$

    I hope this is helpful.



Re: Help with Regular Expressions
by nemesdani (Friar) on Apr 10, 2012 at 19:14 UTC
    Or there is the base module File::Find. $_ always holds the current file/directory name as it runs through the directory tree. I think it's what you should use, no need for regexes.
    An excellent intro is here: Beginners guide to File::Find

    I'm too lazy to be proud of being impatient.

      Actually, I am using that module, and unless I am missing something, when it's a directory the $_ will either contain the full path, or the directory name of the current directory.

      using my example above I would get a list like:

    • DirD
    • DirE
    • Enabling no_chdir => 1 will produce

    • \\DirA\DirB\DirC\DirD
    • \\DirA\DirB\DirC\DirD\DirE
    • Which I can then use the File::Spec->abs2rel and get \DirD\DirE

      The reason I am after \DirD\DirE is I want to then append this to another base path to see if a file / directory exist in that location

        Oh, I slightly misunderstood your question, forgive me. In this case, I don't know any better solution than Riales', and I still think an OS-independent regex would be too much trouble for this particular problem.

        I'm too lazy to be proud of being impatient.
Re: Help with Regular Expressions
by Anonymous Monk on Apr 11, 2012 at 09:28 UTC
    What's wrong with: $CurrentPath =~ s/^\Q$BasePath\E//;?
      Anonymous Monk,

      Absolutely nothing and Thank You!

      I felt there was a simpler way, yet my searches for understanding on quoted constructs were not clearly showing me some good practical examples.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://964383]
Approved by ww
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (7)
As of 2018-01-22 03:39 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (231 votes). Check out past polls.