Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matchstr not matching regex in vimscript

Tags:

regex

vim

The following vimscript code is inside of a function and is not coming up with a match, and I don't understand why.

let curLine= '[exec] setup/src/LinkedList.cs(6,15): warning CS0659:'
echo curLine
let matchs= matchstr(curLine,'[(][0-9]+[,][0-9]+[)]')
if matchs == ''
    echo 'no match'
    return
endif
echo 'match found'

When I run the function inside Vim 'no match' is echoed. What am I doing wrong? I tried testing this regex using http://regexpal.com/ and it seems to work the way I expect (The parentheses with line and character number inside are highlighted)

like image 829
still_dreaming_1 Avatar asked Dec 20 '13 19:12

still_dreaming_1


2 Answers

should be in this way:

let matchs= matchstr(curLine,'[(][0-9]\+[,][0-9]\+[)]')

The matching is always done like 'magic' is set and 'cpoptions' is empty.

Because it matches like "magic", we need to escape the + in the regex to give it special meaning. For more details regarding magic you can read :h magic.

like image 105
Kent Avatar answered Oct 25 '22 03:10

Kent


Even though this answer was originally answered by Kent, which fixed the issue for the OP, I myself was severely dissatisfied by his answer due to reasons I mention in comments under his answer. So, here's my take on an actual explanation of what to do in this case.


The problem with your match pattern is that your + quantifier is not interpreted as a quantifier, because the "magic mode" does not by default interpret these as special characters. This can be fixed by either setting the magic mode to 'very magic', which makes it behave like you describe in your question, or by prefixing any special characters listed in :help magic with the necessary backslashes. Not listed there are ranges like you're using here to select for [0-9]. Those only work in either 'magic' or 'very magic' modes.

Considering you're in regular 'magic' mode, you need to escape your quantifiers, and you don't need to do anything to special characters other than those in $.*~[]. This means your code would most efficiently be as follows:

let matchs= matchstr(curLine,'([0-9]\+,[0-9]\+)')

Here I've changed [(], [,] and [)] to their respective plain text characters for brevity, because in regular 'magic mode' they require no special way of escaping. I've also escaped the + in order to have it interpreted as a quantifier, which is the same Kent did in the other answer on this question.

Another way to make your expression work exactly as you are asking for, would be to prefix the expression with \v. This turns your pattern into 'very magic' mode, which acts just like you are probably expecting it to in your question:

let matchs= matchstr(curLine,'\v[(][0-9]+[,][0-9]+[)]')

Or in a shorter syntax, by escaping the brackets with a backslash instead of a group, and not escaping the comma (since it is not a special character):

let matchs= matchstr(curLine,'\v\([0-9]+,[0-9]+\)')

Any of these three lines would fix your problems.

Again, for a full list of characters that do or do not need escaping in specific 'magic' modes, see :help magic. You can also check out https://andrewra.dev/2011/05/08/vim-regexes/ for a blog that explains several of these concepts.

like image 33
Joeytje50 Avatar answered Oct 25 '22 02:10

Joeytje50