Vim regex to substitute/escape pipe characters - regex

Let's suppose I have a line:
a|b|c
I'd like to run a regex to convert it to:
a\|b\|c
In most regex engines I'm familiar with, something like s%\|%\\|%g should work. If I try this in Vim, I get:
\|a\||\|b\||\|c
As it turns out, I discovered the answer while typing up this question. I'll submit it with my solution, anyway, as I was a bit surprised a search didn't turn up any duplicates.

vim has its own regex syntax. There is a comparison with PCRE in vim help doc (see :help perl-patterns).
except for that, vim has no magic/magic/very magic mode. :h magic to check the table.
by default, vim has magic mode. if you want to make the :s command in your question work, just active the very magic:
:s/\v\|/\\|/g

Vim does the opposite of PCRE in this regard: | is a literal pipe character, with \| serving as the alternation operator. I couldn't find an appropriate escape sequence because the pipe character does not need to be escaped.
The following command works for the line in my example:
:. s%|%\\|%g

If you use very-magic (use \v) you'll have the Perl/pcre behaviour on most special characters (excl. the vim specifics):
:s#\v\|#\\|#g

Related

Basic Vim - Search and Replace text bounded by specific characters

Say I wanted to replace :
"Christoph Waltz" = "That's a Bingo";
"Gary Coleman" = "What are you talking about, dear Willis?";
to just have :
"Christoph Waltz"
"Gary Coleman"
i.e. I want to remove all the characters including and after the = and the ;
I thought the regex for finding the pattern would be \=.*?\;. In vim, I tried :
:%s/\=.*?\;$//g
but it gave me an Invalid Command error and Nothing after \=. How do I remove the above text? Apologies, but I'm new to this.
Vim's regular expression dialect is different; its escaping is optimized for text searches. See :help perl-patterns for a comparison with Perl regular expressions. As #EvergreenTree has noted, you can influence the escaping behavior with special atoms; cp. :help /\v.
For your example, the non-greedy match is .\{-}, not .*?, and, as mentioned, you mustn't escape several literal characters:
:%s/ =.\{-};$//
(The /g flag is superfluous, too; there can be only one match anchored to the end via $.)
This is because of vim's weird handling of regexes by default. Instead of \= interpreting as a literal =, it interprets it as a special regex character. To make vim's regex system work more normally, you can prefix it with \v, which is "very magic" mode. This should do the trick:
%s/\v\=.*\;$//g
I won't explain how vim enterprets every single character in very magic mode here, but you can read about it in this help topic:
:help /magic

Why would a regex work in Sublime and not in vim?

Tried searching for regex found in this answer:
(,)(?=(?:[^']|'[^']*')*$)
I tried doing a search in Sublime and it worked out (around 700 results). When trying to replace the results it runs out of memory. Tried /(,)(?=(?:[^']|'[^']*')*$) in vim for searching first but it does not find any instances of the pattern. Also tried escaping all the ( and ) with \ in the regex.
Vim uses its own regular expression engine and syntax (which predates PCRE, by the way) so porting a regex from perl or some other editor will most likely need some work.
The many differences are too numerous to list in detail here but :help pattern and :help perl-patterns will help.
Anyway, this quick and dirty rewrite of your regular expression seems to work on the sample given in the linked question:
/\v(,)(\#=([^']|'[^']*')*$)
See :help \#= and :help \v.
One possible explanation is that the regular expression engine used in Sublime is different than the engine used in vim.
Not all regex engines are created equal; they don't all support the same features. (For example, a "negative lookahead" feature can be very powerful, but not all engines support it. And the syntax for some features differs betwen engines.)
A brief comparison of regular expression engines is available here:
http://en.wikipedia.org/wiki/Comparison_of_regular_expression_engines
Unfortunately Vim uses a different engine, and "normal" regular expressions won't work.
The regex you've mentioned isn't perfect: it doesn't skip escaped quotes, but, as I understand, it's good enough for you. Try this one, and if it doesn't match something, please send me that piece.
\v^([^']|'[^']*')*\zs,
A little explanation:
\v enables very magic search to avoid complex escaping rules
([^']|'[^']*') matches all symbols but quote and a pair of qoutes
\zs indicates the beginning of selection; you can think of it as of a replacement for lookbehind.
You have to escape the |, otherwise it doesn't work under vim. You should also escape the round brackets, unless you are searching for the '(' or ')' characters.
More information on regex usage in vim can be found on vimregex.com.

non-greedy multiline search in vim

I am trying to search ruby file and find all methods (before autoreplacing them later).
In vim, i use following regexp:
/\vdef.*(\n.*){-}end
However even though i use "{-}", it selects whole file's contents.
vim uses \_. to include the newline character to the common ..
/\vdef\_.{-}end
In my version of Vim, you need to escape the {, as well as using \_. as other answers have said:
/def\_.\{-}end
Try following regex.
/\vdef(\n|.){-}end
.* was culprit in your case

Perform a non-regex search/replace in vim

When doing search/replace in vim, I almost never need to use regex, so it's a pain to constantly be escaping everything, Is there a way to make it default to not using regex or is there an alternative command to accomplish this?
As an example, if I want to replace < with <, I'd like to just be able to type s/</</g instead of s/\</\&lt\;/g
For the :s command there is a shortcut to disable or force magic. To turn off magic use :sno like:
:sno/search_string/replace_string/g
Found here: http://vim.wikia.com/wiki/Simplifying_regular_expressions_using_magic_and_no-magic
Use this option:
set nomagic
See :help /magic
The problem is primarily caused by confusion about the role of the & in the replacement string. The replacement string is not a reg-ex, although it has some special characters, like &. You can read about role of & in replacement string here: :h sub-replace-special .
I suspect the main problem for OP is not necessarily typing the extra backslashes, but rather remembering when a backslash is needed and when not. One workaround may be to start making use of "replacement expressions" when unsure. ( See :h sub-replace-expression.) This requires putting a `\=' in replacement string but for some people it may give you more natural control over what's being substituted, since putting a string literal in single quotes will give you the replacement string you want. For example, this substitute does what OP wants:
:s/</\='<'/g
If you want to search literally, you can use the \V regex atom. This almost does what you want, except that you also need to escape the backslash. You could define your own search command, that would search literally. Something like this:
:com! -nargs=1 Search :let #/='\V'.escape(<q-args>, '\/')| normal! n
And then use :Search /foobar/baz
For Substitute, you could then after a :Search command simply use
:%s//replace/g
since then Vim would implicitly pick up the last search item and use the for replacing.
(Just want to give you some ideas)
Here’s how to disable regular expression search/replace only in command mode:
autocmd CmdWinEnter * set nomagic
autocmd CmdWinLeave * set magic
All plugins that depends on regular expression such as white-space remover should works as usual.
Have you enabled magic?
:set magic
Try the Edit Find and replace on the menu bar.

Multi-line regex support in Vim

I notice the standard regex syntax for matching across multiple lines is to use /s, like so:
This is\nsome text
/This.*text/s
This works in Perl for instance but doesn't seem to be supported in Vim. Instead, I have to be much more specific:
/This[^\r\n]*[\r\n]*text/
I can't find any reason for why this should be, so I'm thinking I probably just missed the relevant bits in the vim help.
Can anyone confirm this behaviour one way or the other?
Yes, Perl's //s modifier isn't available on Vim regexes. See :h perl-patterns for details and a list of other differences between Vim and Perl regexes.
Instead you can use \_., which means "match any single character including newline". It's a bit shorter than what you have. See :h /\_..
/This\_.*text/