(vim) regex: masking text with help of pattern - regex

Am i correct to understand, that the definition
:range s[ubstitute]/pattern/string/cgiI
suggests that in the string part indeed only strings are to be used, that is patterns not allowed? What i would like to do is do replacement of say any N symbols at position M with X*N symbols, so i would have liked to use something like this:
:%s/^\(.\{10}\).\{28}/\1X\{28}/g
Which does not work because \{28} is interpreted literally.
Is writing the 28 XXXXX...X in the replace part the only possibility?

You can use expressions in the replacement part via \=. You have to access the match via submatch(), and join it together with the static string, which you can generate via repeat():
:%s/^\(.\{10}\).\{28}/\=submatch(1) . repeat('X',28)/g

The only regex constructs allowed in the replacement part are numbered groups: \1 \2 \3 etc. The repeating construct {28} is not valid there, though it's a clever idea. You'll have to use 28 X's.

Another alternative is using a expression in the replacement part:
:%s/^\(.\{10}\).\{28}/\=submatch(1).repeat("X",28)/g
The first matched group is obtained with submatch(1). For more information see :h sub-replace-expression.

Related

Regex match sequence more than once

How come for something that simple I can't find an answer after looking one hour in the internet?
I have this sentence:
HeLLo woRLd HOw are YoU
I want to capture all groups that consist of two following capital letters
[A-Z]{2}
The regex above works but capture only LL (the first two capital letters) while I want LL in one group and in the other groups also RL HO
Most regular expression engines expose some way to make your expression global. This means that your expression will applied multiple times. This global flag is usually denoted with the /g marker at the end of your expression. This is your regular expression without the /g flag, while this is what happens when you apply said flag.
Different languages expose such functionality differently, in C# for instance, this is done through the Regex.Matches syntax. In Java, you use while(matcher.find()), which keeps providing sub strings which match the pattern provided.
EDIT: I am not a Python person, but judging from the example available here, you could do something like so:
it = re.finditer(r"[A-Z]{2}", "HeLLo woRLd HOw are YoU")
for match in it:
print "'{g}' was found between the indices {s}".format(g=match.group(), s=match.span())
You can not have multiple groups in this case, but you can have multiple matches. Add the global flag to your regex and use a method to match the regex.
For javscript, it would be /[A-Z]{2}/g.
The method most probably returns an Array of matches, and you can use index to access them.

Regular expression to split optional groups

Full string syntax is: "db:server:port"
Server and port are optional, i.e. can have partial strings, such as:
db
or
db:server
Trying to use:
(.*):?(.*)?:?(.*)?
selects the whole string
Please advise.
Give this one a shot:
([^:]*?):?([^:]*?):?([^:]*?)$
Not sure what language you're using, so it may not work.
Example: http://regex101.com/r/eQ6bF0
Note on the example it's set for a global/multiline match - beware that this will match across newlines if you don't use the correct modifier.
You didn't specify a language that I can see, so there may be different specific answers, but the basic problem is that .* will match a ":" character. That means the first term will suck the entire string in. I would use ([^:]*) instead of (.*).
You can try this:
([^:]+)(?::([^:]+)(?::([^:]+))?)?
I think this is what you're looking for:
(db|:server|:port)
will match any and all of these:
db:server:port
db
db:server
Working example:
http://regex101.com/r/rK1lI5

How to recall the match side on the substitution side of your replace command?

For example, to transform foo(a,b,c) into foo(ax,bx,cx) with a single command you would need something like:
:s/[abc]/MATCHED_CHARACTERx/g
What is the correct syntax for this substitution?
With escaped parentheses \(...\) in the search pattern you can mark sections that you want to use in the replace pattern. Each section in parentheses can be accessed by \1, \2, \3.... \0 matches the whole search pattern.
So, for your example, you could either use
:%s/[abc]/\0x/g
or, to be more specific,
:%s/foo(\(.\),\(.\),\(.\))/foo(\1x,\2x,\3x)/g
The second pattern will match only foo(<any>,<any>,<any>) instead of all occurrences of a,b,c.
The & is a synonym of \0 and stands for the entire match. So you can also use &x in your example replacement. This also works in many other tools, e.g. sed.

Regex Extract in Google Docs for capturing the end of variable strings

In Google Docs, if I have a series of strings like "Something.Here.Search.Term.Chicago", where the last component after "Term." can be anything.
How do I use regex extract to only capture what comes after "Term."?
Note that the length of the string varies before Term so I can't use Left or Right and position since it's always different.
You can use a positive look-behind as well, to avoid having to capture with groups:
/(?<=Term\.).*/
Though depending on the language you are implementing this with, it may not support look-behinds (namely JavaScript).
If you don't want to mess about with capturing groups and you know the component you want is the substring between the last . and the end of the string, you could use
[^.]+$
Here's what worked for me using you sample data:
=REGEXREPLACE(A1; ".*Term.(.*)" ; "$1")
I don't know Google Docs, but normally in regular expressions, you would do
"Something\.Here\.Search\.Term\.(.*)"
The () means capture and remember the pattern within. In this case .* means everything. You can usually access the pattern as $1, etc. in Javascript.
See Examples of Regular Expressions
What about using a "look-ahead" expression (?=),
then something repeated followed by a word boundary?
Something like this:
(?=Term\\.).*\W

Extract and use a part of string with a regex in GVIM

I've got a string:
doCall(valA, val.valB);
Using a regex in GVIM I would like to change this to:
valA = doCall(valA, val.valB);
How would I go about doing this? I use %s for basic regex search and replace in GVIM, but this a bit different from my normal usages.
Thanks
You can use this:
%s/\vdoCall\(<(\w*)>,/\1 = doCall(\1,/
\v enables “more magic” in regular expressions – not strictly necessary here but I usually use it to make the expressions simpler. <…> matches word boundaries and the in-between part matches the first parameter and puts it in the first capture group. The replacement uses \1 to access that capture group and insert into the right two places.