match and matchend with a negative lookbehind

29 views
Skip to first unread message

rameo

unread,
Apr 5, 2012, 2:53:13 PM4/5/12
to vim...@googlegroups.com
I noted a strange behavior with match and matchend when I use a regex with a negative lookbehind.

p.e.
text in document:

-2 3-4-5-6-7-8

search string: \([0-9-]\@<!-\)\?\d[0-9]*
it highights -2 3 4 5 6 7 8 (as I aspected)

but when I check the match and matchend in order to copy the matches, it does include the "-" between 3-4 4-5 5-6 6-7 7-8
Does match and matchend not work with a negative lookbehind?

(please see attachment if the search string doesn't show up correct)

match-matchend.jpg

Ben Fritz

unread,
Apr 5, 2012, 6:02:48 PM4/5/12
to vim...@googlegroups.com
On Thursday, April 5, 2012 1:53:13 PM UTC-5, rameo wrote:
> I noted a strange behavior with match and matchend when I use a regex with a negative lookbehind.
>
> p.e.
> text in document:
>
> -2 3-4-5-6-7-8
>
> search string: \([0-9-]\@<!-\)\?\d[0-9]*
> it highights -2 3 4 5 6 7 8 (as I aspected)
>

Highlights when you do what? Are you talking about a simple / search or a syntax highlight or something else?

> but when I check the match and matchend in order to copy the matches, it does include the "-" between 3-4 4-5 5-6 6-7 7-8

match() and matchend() are functions which work on a string, they don't look at buffer text. In what way did you use these on the text? How do you know it includes the "-"? Or are you referring to something other than match() and matchend()?

> Does match and matchend not work with a negative lookbehind?
>

They should. Please give the EXACT command you ran, and tell exactly what you expected, and exactly what happened instead. A script which will reproduce what you see would be best.

John Little

unread,
Apr 5, 2012, 11:13:55 PM4/5/12
to vim...@googlegroups.com
On Friday, April 6, 2012 10:02:48 AM UTC+12, Ben Fritz wrote:
> Please give the EXACT command you ran...

Perhaps this script will illustrate:

let s = '-2 3-4-5-6-7-8'
let p = '\([0-9-]\@<!-\)\?\d[0-9]*'
let [start, end] = [0, 0]
while 1
let start = match(s, p, end)
let end = matchend(s, p, end)
if start == -1
break
endif
echo s[start : end-1]
endwhile

I get:

-2
3
-4
-5
-6
-7
-8

It would appear that using the third parameter to match() and matchend(), the match is done as if on a substring starting at the parameter, so the look behind assertion does not see what's there in the original string.

This is unlike searching in a buffer; the look behind assertion does look behind the start position of the search. Rameo, is this what you're getting at?

Regards, John

rameo

unread,
Apr 6, 2012, 2:40:25 AM4/6/12
to vim...@googlegroups.com
Hi Ben and John,

Thank you for your answers.

Ben,
Yes I'm talking about a simple / search
Sorry that I didn't add an example.
Please see the example in John example.
This is exactly what I've done and noted.

John,
Yes, that's what I getting.
I had never seen such a "strange" behavior with match() and matchend()

Ben Fritz

unread,
Apr 6, 2012, 11:04:19 AM4/6/12
to vim...@googlegroups.com

I think you've analyzed it perfectly! Looking closer at the help for match(), I see:

For a String, if {start} > 0 then it is like the string starts
{start} bytes later, thus "^" will match at {start}. Except
when {count} is given, then it's like matches before the
{start} byte are ignored

So with only 3 arguments, from this help text, I would expect exactly the results given, for the reason given.

However, this gave me a hint to fix the problem. With a minor tweak:

let s = '-2 3-4-5-6-7-8'
let p = '\([0-9-]\@<!-\)\?\d[0-9]*'
let [start, end] = [0, 0]
while 1

" count=1 to ignore previous matches rather than making the string
" start at a new place
let start = match(s, p, end, 1)
let end = matchend(s, p, end, 1)


if start == -1
break
endif
echo s[start : end-1]
endwhile

It works as intended. With this script, I get:

rameo

unread,
Apr 6, 2012, 12:02:38 PM4/6/12
to vim...@googlegroups.com

Works great!
I adapted it in the function copymatches which I once found on wikia.com
http://vim.wikia.com/wiki/Copy_the_search_results_into_clipboard
and it works.
Hope it will work in all documents ;)


Reply all
Reply to author
Forward
0 new messages