Friday, February 26, 2016

Re: Search for line containing stringB, not preceded by a line containing stringA

On Friday, February 26, 2016 at 4:58:01 PM UTC-5, Ben Fritz wrote:
> On Friday, February 26, 2016 at 3:25:33 PM UTC-6, Paul wrote:
>> On Friday, February 26, 2016 at 12:26:21 PM UTC-5, Ben Fritz wrote:
>>> On Friday, February 26, 2016 at 9:50:50 AM UTC-6, Paul wrote:
>>>>>>
>>>>>> \(stringA.*\n\)\@<!.*stringB
>>>>>> \(stringA.*\n\)\@<!\(.*stringB\)
>>>>>>
>>>>>
>>>>> Move the newline outside of your negative look-behind, then
>>>>> start the match using \zs after the newline if you only want to
>>>>> match the 2nd line.
>>>>>
>>>>> Make it work on the 1st line as well by temporarily inserting a
>>>>> blank line at the top, or checking it manually, if needed.
>>>>>
>>>>> Here's what I mean, if my description isn't clear:
>>>>> \(stringA.*\)\@<!\n\zs.*stringB
>>>>
>>
>> Your expression works as you said. Thanks.
>>
>> I am a bit confused as to *why* it works. If my guess as to why my
>> original expressions failed is correct, it should apply to your
>> expression as well.
>
> Yours is: \(stringA.*\n\)\@<!.*stringB
>
> Translated: match any text followed by "stringB", as long as there
> is not "stringA" and some text followed by a newline, immediately
> before.
>
> As you figured out, this matches where you don't want it to, because
> there are multiple locations in the stringB line where you don't
> have a newline immediately before, so "stringA...followed by a
> newline" will not match.
>
> Now look at the subtle difference in mine:
> \(stringA.*\)\@<!\n\zs.*stringB
>
> I.e. match any text followed by stringB, if it has a line ending
> just before it, as long as there is not "stringA" and some text just
> before the newline.
>
> The key is that I'm forcing the newline to match. Thus your
> .*stringB is forced to match starting at the beginning of the line,
> so you can't just move forward into the line to find a place where
> \n doesn't match as with your pattern.

Actually, your explanation cleared up a misunderstanding that I had.
In my expression, I pictured .* as a spring that was trying to expand
and maximize its length, as long as it was anchored on stringA on the
left end, and by \n on the right end. In fact it doesn't have to be;
it can match text on the stringB line; or, more accurately, text on
the stringB line can fulfill the requirement of not matching, which is
not the intent of the expression. Your expression prevents this
unwanted effect. Thanks for that! There's a reason that regexps have
thrived despite their zany incarnations and hard-to-visualize effects.

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments: