It looks like your nasty regex was not nasty enough... :-)
The search would have to be changed to this:
This includes quite a few uncommon things and so many parenthesis... Let's see what we have in there:
The Caret (
The caret is used to mean beginning of the line. I think we're already familiar with this one.
An important point, the
^ does not work except as the very first character in your pattern. After the it is taken verbatim. To include a beginning of line within your expression you need to use
\_^. However, in our situation we did not need that.
(There is a similar phenomena with
The first and last parenthesis (
\( ... \))
The first and last parenthesis are used on their own which means it will grab whatever appears inside and set it in parameter
\1. You already used that in your own regex, so I'll assume you also are familiar with this one.
The second set of parenthesis
As you may notice, there is a second set of parenthesis followed by an asterisk
\( ... \)*. This means we are looking for whatever matches any number of times. This is the usual way of using the asterisk so you should be familiar with it.
The third set of parenthesis, OR, and
Yes, there are actually three parenthesis before the word
Show. This last set is necessary for two reasons: the
\| and the following
In regard to the OR operation, you should already be familiar with it.
Show\|Hide or Hide\|Show
The order does not matter here. The
\ is necessary in front of the
| to work in vim.
The parenthesis around this expression allows us to follow the expression by something. Here the
This one is much less familiar. It means if not matched. The use of this is not very easy, though, but you need to follow that expression with what you want to extract which should not match said expression. This is why we have
\_. behind that pattern.
\_. means match anything whatsoever. Contrary to the
. on its own, which doesn't match the
\n character. In other words, we match any character on any number of lines unless it matches
Note that the parenthesis around that expression are also important as is the asterisk, so this whole thing is really what makes it work:
a.k.a. match whatever up to the next
Hide characters (note that it would also match
HideMe, etc. you should be able to use
\> if it is necessary to match the word exactly.)
Side Note: to search on multiple lines, it is also possible to use the
\n character in the pattern. However, it's not as versatile than the
Now the section has to include
SetFontSize 28 as well. Just like you had in your regex. If no
SetFontSize 28 appears in that section, try the search again on the next section.
Because of the negation above (the match except
Hide) the search doesn't leak to the next section, taking the risk of messing it up.
The replacement is just the same as you had it:
We use the parenthesis in the Search so the
\1 works as expected.
Complete Search and Replace
The resulting patterns goes like this:
:%s/^Hide\(\(\(Show\|Hide\)@!\_.\)*\)SetFontSize 28/Hide\1SetFontSize 18/
\(Show\|Hide\) should include all the possible headers.
Regex to match any character including newline (
Search for lines not containing pattern and other helpful searches (
Vim documentation: pattern (
Hideblock have a
SetFontSizeline (whatever be the value)? If so, you could use
whatever be the valuewould cause trouble, your solution only works if every
Hideblock have a
SetFontSizeline and it's value is exactly
28, otherwise, it matches until
28of another block.