Rancho
Rancho

Reputation: 309

Substitute all but the last occurrence using perl

I have a string say "a/b/c/d/e" and I want to replace all except the last / to . i.e my output should be a.b.c.d/e.

How do I modify my substitute command s/\//./g to do the same? Also note the hierarchy doesn't always have 4 "/". It can be any number.

Upvotes: 3

Views: 1022

Answers (1)

zdim
zdim

Reputation: 66873

Replace all / for which there is a / further down the string; thus that excludes the last /

perl -wE'$_ = q(a/b/c/d/e); s{/(?=.*?/)}{.}g; say'

This uses the positive lookahead, (?=...) to assert the presence of / further down (after .*?), without consuming anything.


Another way is to capture with a negated character class pattern (and then put that back in the string) and use only the fixed string / in the lookahead

s{/([^/]*)(?=/)}{.$1}g;

The first approach above with a / match and a lookahead for the rest turns out to be faster. The likely reason is the capturing in the ([^/]*) approach (and it has to copy that back in the string), whereby the first approach does a single character overwrite (the .*? doesn't backtrack).

Benchmarked: 126% faster under v5.10.1 and v5.27.2 (desktop) and 110% with v5.16.1 (new server). Tested with 4-10 char long strings for four path components.

Thanks to ikegami for noting this and prompting for, and commenting on, the comparison.

Upvotes: 7

Related Questions