Multiline regex replacement in sed/vi - regex

I need to replace this statement in a named.conf with regex
masters {
10.11.2.1;
10.11.2.2;
};
All my approaches with sed/vi do not work
%s/masters.*\}\;//g
does not match. Also tried with /s \s etc to match the newline.

In vim, you can force a pattern to match across newlines with \_, for example:
%s/masters {\_[^}]*};//g
It's important to replace .* with something more conservative like [^}]* if you prefix with \_, because * is greedy, so \_.* will try to match everything to the end of the document.

Related

Regex to match within brackets in vim

Let's say I have the following text:
new_item['uid']
And I want to capture everything within the [ ... ]. So in this case grab the 'uid'. Normally I could use something like:
\[([^\]]+)]
To match this (start with the opening bracket and get everything until the closing bracket). But without the character classes, or negated character class in vim, how would I do something similar?
If you want to have a capture group with (..), you need the verymagic mode, otherwise you have to escape the ( and ), similar to the BRE.
So both give the matched part in \1:
\[\([^]]*\)
and (\v tells vim to match in verymagic mode)
\v\[([^]]*)
You could use .\{-} in place of .*? to make a lazy dot match:
\[(.\{-})\]
in addition to the other answers, you could use \v\[\zs.{-}\ze\] to only highlight the text within \zs and \ze, see :h \ze

Regex: find string between curly brackets, which itself contains curly brackets

Suppose a string on the following format:
Use \hyperlink{aaa}{apple {pear} banana} and \hyperlink{bbb}{banana {pear} {apple}}.
I want to extract:
\hyperlink{aaa}{apple {pear} banana}
\hyperlink{bbb}{banana {pear} {apple}}
What regex could be used for such an extraction?
I got stuck with this:
\\hyperlink{\S+}{.+}
Here how you can do it with a recursive regex
\\hyperlink\{[^}]+?\}(\{(?>[^{}]+|(?1))+\})(?=\s|$)
Regex Demo
Recursive regex
If there is no arbitrary nesting, you can use a pattern with negated }{ like
\\hyperlink{[^}{]*}{[^}{]*(?:{[^}{]*}[^}{]*)*}
Similar this answer but unrolled. See the demo at regex101. To {extract} use groups (demo).
Depending on your environment / regex flavor it can be necessary to escape the opening { by a backslash for the braces that are not inside a character class to match them literally.
Further note that \S+ can consume } and .+ can match more than desired if unaware.

Regex replace within match

In Notepad++ RegEx, I want to search for all strings starting with a tilde and terminating with \n, and within each match replace all spaces with non-breaking spaces.
That is, I want to find all instances of \~.*^, and within the resulting $0, replace all [Space]s with [Non-breaking Space].
Is this possible?
You can use the following to match:
(?:~|\G(?<!^))\S*\K\s
Or try:
(?:~|\G(?!^))\S*\K[ ]
And replace with non breaking space
See DEMO
Credits
With fixed-width pattern lookbehind regex engines (e.g., Perl):
s/(~.*?) {2,}/\1 /g
with variable-width pattern lookbehind regex engines:
s/(?<=\~.*) {2,}/ /g
or with Vim:
s/\(\~.*\)#<= \{2,}/ /g
I'm not sure about Notepad++. Hopefully you can work it out based on the above.

NOTEPAD++ REGEX - I can't get what's in between two strings, I don't get it

I'm so close to understanding regex. I'm a bit stumped, I thought i understood lazy and greedy.
Here is my current regex: <g_n><!\[CDATA\[([^]]+)(?=]]><\/g_n>)
My current regex makes:
<g_n><![CDATA[xxxxxxxxxx]]></g_n>
match to:
<g_n><![CDATA[xxxxxxxxxx
But I want to make it match like this:
xxxxxxxxxx
You want
<g_n><!\[CDATA\[(.*?)]]></g_n>
then if you want to replace it use
\1
in the replacement box
Your matching the whole string, the brackets around the .*? match all of that and put it in the \1 variable
So the match will be all of the string with \1 referring to what you want
To change the xxxxx
Regex :
(<g_n><![CDATA[)(?:.*?)(]]></g_n>)
Replacement
\1WHAT YOU WANT TO CHANGE TO\2
It looks like you need to add escape slashes to the two closing square brackets, as they are literals from the string you're parsing.
<g_n><!\[CDATA\[.*+?\]\]><\/g_n>
^ ^
Any square brackets not being escaped by backslashes will be treated as regex operational brackets, which in this case won't catch the input string.
EDIT, I think the +? is redundant.
\[.*\]\]> ...
should suffice, since .* means any character, any amount of times.
Tested with notepad++ 6.3.2:
find: (<g_n><!\[CDATA\[)([^]]+)(?=]]></g_n>)
replace: $1WhatYouWant
You can replace + by * in the pattern to match void CDATA:
<g_n><![CDATA[]]></g_n>

vim regex find and replace

I want to use a regex to replace some strings in my file. I search for:
%s/^ [a-z]*/ /
what I want to do is to replace every [a-z]* that have 2 whitespaces with the sane [a-z] prepended with 4 whitespaces. Is there any "inplace" replacement or how would I reach that with vim?
With best regards
:%s/ \([a-z]*\)/ \1/g
should do the job; beware of running this multiple times, though because the result of the replace will match the input pattern :)
I find it more straightforward to use the \ze object to define the end of the match:
:%s/ \ze[a-z]*/ /g
so the [a-z]* is not included in the replace, but just used to match the relevant spaces.