2017-10-18 11 views
4

J'ai une chaîne dire "a/b/c/d/e" et je veux remplacer tous sauf le dernier / à. ma sortie devrait être a.b.c.d/e. Comment modifier ma commande de remplacement s/\//./g pour faire la même chose? Notez également que la hiérarchie n'a pas toujours 4 "/". Cela peut être n'importe quel nombre.Remplacer tout sauf la dernière occurrence en utilisant perl

+0

Un rappel, s'il vous plaît voir [Que dois-je faire quand quelqu'un répond à ma question?] (Http://stackoverflow.com/help/someone-answers) – zdim

Répondre

7

Remplacer tous les / pour lesquels il existe un / plus bas dans la chaîne; qui exclut le dernier /

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

Il utilise le positive lookahead, (?=...), d'affirmer la présence de / plus bas (après .*?) sans consommer quoi que ce soit.


Une autre façon est de capturer avec un modèle de classe de caractères niée (puis remettre tout ça dans la chaîne) et utiliser uniquement la chaîne fixe / dans la préanalyse

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

Cependant, la première approche ci-dessus avec un match / et un lookahead pour le reste s'avère être plus rapide. La raison probable: la capture dans l'approche ([^/]*) (et il doit la recopier dans la chaîne) tandis que la première effectue un seul remplacement de caractère (le .*? ne revient pas en arrière).

Benchmark: 126% plus rapide sous v5.10.1 et v5.27.2 (bureau) et 110% avec v5.16.1 (nouveau serveur). Testé avec 4 à 10 caractères longs pour quatre composantes de chemin.

Merci à ikegami de le noter et de demander et de commenter la comparaison.

+0

Peut-être pourriez-vous expliquer pourquoi cela fonctionne. – xxfelixxx

+0

@xxfelixxx Très bien, merci. Édité. – zdim

+3

Plus efficace? 's {/([^/]*)(?=/)}{.$ 1} g;' – ikegami