Regular expression, search and replace until a certain point

Problem

I have a file full of lines like

convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it 

I want to search and replace such that I get

 convert/these/dots/to/forward/slashes/but.leave.these.alone/i.mean.it 

. converted to / up to the first slash

Question

How to write search and replace regular expressions to solve my problem?

Attempt to solve

I tried to use the look with perl, but the look of variable length is not implemented.

 $ echo "convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it" | perl -pe 's/(?<=[^\/]*)\./\//g' Variable length lookbehind not implemented in regex m/(?<=[^/]*)\./ at -e line 1. 

Bypass

Variable-length perspectives are implemented, so you can use this dirty trick.

 $ echo "convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it" | rev | perl -pe 's/\.(?=[^\/]*$)/\//g' | rev convert/these/dots/to/forward/slashes/but.leave.these.alone/i.mean.it 

Is there a more direct solution to this problem?

+4
source share
2 answers
 s/\G([^\/.]*)\./\1\//g 

\G is a statement that matches a period at the end of a previous match. This ensures that each subsequent match immediately follows the last.

Matches:

 \G # start matching where the last match ended ([^\/.]*) # capture until you encounter a "/" or a "." \. # the dot 

Replaces:

 \1 # that interstitial text you captured \/ # a slash 

Using:

 echo "convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it" | perl -pe 's/\G([^\/.]*)\./\1\//g' # yields: convert/these/dots/to/forward/slashes/but.leave.these.alone/i.mean.it 

Alternatively, if you are a purist and do not want to add the captured subpattern back - avoid what might be more efficient, but I'm not sure - you could use \K to limit "real" to match only . , and then simply replaced by / . \K essentially "forgets" what was matched to this point, so the final match ultimately returns only after \K

 s/\G[^\/.]*\K\./\//g 

Matches:

 \G # start matching where the last match ended [^\/.]* # consume chars until you encounter a "/" or a "." \K # "forget" what has been consumed so far \. # the dot 

Thus, all text suitable for replacement is simply " . ".

Replaces:

 \/ # a slash 

The result is the same.

+5
source

You can use substr as an lvalue and do the substitution on it. Or transliteration, as I did below.

 $ perl -pe 'substr($_,0,index($_,"/")) =~ tr#.#/#' convert.these.dots.to.forward.slashes/but.leave.these.alone/i.mean.it convert/these/dots/to/forward/slashes/but.leave.these.alone/i.mean.it 

This finds the first slash instance, extracts the portion of the line before it, and performs transliteration on that portion.

+2
source

All Articles