Umesh Kacha
Umesh Kacha

Reputation: 13676

Perl split string based on forward slash

I am new to Perl, so this is basic question. I have a string as shown below. I am interested in taking date out of it, so thinking of splitting it using slash

my $path = "/bla/bla/bla/20160306";
my $date = (split(/\//,$path))[3];#ideally 3 is date position in array after split
print $date;

However, I don't see the expected output, but instead I see 5 getting printed.

Upvotes: 3

Views: 8898

Answers (3)

zdim
zdim

Reputation: 66881

Since the path starts with the pattern / itself, split returns a list with an empty string first (to the left of the first /); one element more. Thus the posted code miscounts by one and returns the one before last element (subdirectory) in the path, not the date.

If date is always the last thing in the string you can pick the last element

my $date = (split '/', $path)[-1];

where i've used '' for delimiters so to not have to escape /. (This, however, may confuse since the separator pattern is a regex and // convey that, while '' may appear to merely quote a string.)


This can also be done with regex

my @parts = $path =~ m{([^/]+)}g;

With this there can be no inital empty string. Or, the last part can be picked out of the full list as above, with ($path =~ m{...}g)[-1], but if you indeed only need the last bit then extract it directly

my ($last_part) = $path =~ m{.*/(.*)};

Here the "greedy" .* matches everything in the string up to the last instance of the next subpattern (/ here), thus getting us to the last part of the path, which is then captured. The regex match operator returns its matches only when it is in the list context so parens on the left are needed.


What brings us to the fact that you are parsing a path, and there are libraries dedicated to that.

For splitting a path into its components one tool is splitdir from File::Spec

use File::Spec;

my @parts = File::Spec->splitdir($path);

If the path starts with a / we'll again get an empty string for the first element (by design, see docs). That can then be removed, if there

shift @parts if $parts[0] eq '';

Again, the last element alone can be had like in the other examples.

Upvotes: 6

mkHun
mkHun

Reputation: 5927

Try this

Use look ahead for to do it. It capture the / by splitting. Then substitute the data using / for remove the slash.

my $path = "/a/b/c/20160306";
my $date = (split(/(?=\/)/,$path))[3];
$date=~s/^\///;
print $date;

Or else use pattern matching with grouping for to do it.

my $path = "/a/b/c/20160306";
my @data = $path =~m/\/(\w+)/g;
print $data[3];

Upvotes: 0

Jan
Jan

Reputation: 43169

Simply bind it to the end:

(\d+)$
# look for digits at the end of the string

See a demo on regex101.com. The capturing group is only for clarification though not really needed in this case.

In Perl this would be (I am a PHP/Python guy, so bear with me when it is ugly)

my $path = "/bla/bla/bla/20160306";
$path =~ /(\d+)$/;
print $1;

See a demo on ideone.com.

Upvotes: 1

Related Questions