2

I'm having a hard time writing regexes in vim -- it seems everything I try either requires an escape character or isn't supported. For example, I have a SQL statement that includes something like:

max(if(s.name like 'iTunes' and completion_date is not null, 'Complete', if(s.name like 'iTunes', 'X', null))) iTunes,
max(if(s.name like 'amazon' and completion_date is not null, 'Complete', if(s.name like 'Amazon', 'X', null))) Amazon

And I want to change it from 'itunes' to '%%itunes%%' for the like statement to work. My first attempt was:

  • shiftv to highlight the lines I want to replace
  • s/'([a-z]+)'/'%%\1%%'

To which I get:

E486: Pattern not found: '([a-z]+)'

How would I enter in that regex, and is there a good place to learn about regex use in vim (specifically what's supported and what needs to be escaped)?


Update: even though it's a bit dry, the docs are great here for a comprehensive reference: pattern. And the regex that worked was:

  • s/'\(\a\{2,}\)'/'%%\1%%'/g

A few notes:

  • There is no [a-z]. Need to use \l (lowercase) or or \a (lower or uppercase) instead.
  • Capturing groups need to be escaped on both sides: \(...\) and then reference it with \1.
  • For a repetition, the first part needs to be escaped: \{2,}

Basically, just keep the reference handy as there are a lot of real quirky things here!

2

Yeah, the Vim flavor of regex is a bit different from what you'll find in languages such as Python or Perl.

In particular, you need to escape the sets of parens that mark a group. Also, the + to repeat one or more.

But [a-z] itself works as expected. (Not that there's anything wrong with \a, which is in many senses better... But I just wanted to point out that a character range such as [a-z] will work in Vim regexes.)

This will work:

s/'\([a-z]\+\)'/'%%\1%%'/

But will it match only lowercase letters? Well, it depends! If you have either set ignorecase or set smartcase, then it will match either lowercase or uppercase words, since either of those will make this regex match case-insensitively.

You might want to look into the \v modifier for the "verymagic" mode, which make regexes work closer to how they work in other languages. Parens and + are now metacharacters by default.

s/\v'([a-z]+)'/'%%\1%%'/

You can also force 'ignorecase' behavior by including a \c anywhere in your regex (or make it match case exactly with \C.)

One quite unique feature of Vim regexes is that you can use \zs and \ze to mark the start and end of the actual match. So you can replace a word within quotes without capture groups.

s/\v\c'\zs[a-z]+\ze'/%%&%%/

There are many more features of the Vim regex engine. Hopefully these pointers here will get you started. The docs are really good, so read those too.

| improve this answer | |
1

Vim regex are Basic Regular Expression which predate PCRE. IMHO the former are better for text edition and the latter for scripting. I’ve noticed that often I use search and replace with literal characters, for example, when I need to find myFunction(, and Vim’s default behaviour is good for that. So that’s why you need to escape things like ( and ).

But if you need to write complicated regexes you can change the characters that need to be escaped in scripts and in runtime! I know at first it is confusing, but now I think it is an awesome feature. See :help magic for details, and read this answer, it changed my mind about BRE and helped me understand the magic thing.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.