Interactive search/replace regex in Vim? - regex

I know the regex for doing a global replace,
%s/old/new/g
How do you go about doing an interactive search-replace in Vim?

Add the flag c (in the vim command prompt):
:%s/old/new/gc
will give you a yes/no prompt at each occurrence of 'old'.
Vim's built-in help offers useful info on the options available once substitution with confirmation has been selected. Use:
:h :s
Then scroll to section on confirm options. Screenshot below:
For instance, to substitute this and all remaining matches, use a.

Mark Biek pointed out using:
%s/old/new/gc
for a global search replace with confirmation for each substitution. But, I also enjoy interactively verifying that the old text will match correctly. I first do a search with a regex, then I reuse that pattern:
/old.pattern.to.match
%s//replacement/gc
The s// will use the last search pattern.

I think you're looking for c, eg s/abc/123/gc, this will cause VIM to confirm the replacements. See :help :substitute for more information.

I usually use the find/substitute/next/repeat command :-)
/old<CR>3snew<ESC>n.n.n.n.n.n.n.
That's find "old", substitute 3 characters for "new", find next, repeat substitute, and so on.
It's a pain for massive substitutions but it lets you selectively ignore some occurrences of old (by just pressing n again to find the next one instead of . to repeat a substitution).

If you just want to count the number of occurrences of 'abc' then you can do %s/abc//gn. This doesn't replace anything but just reports the number of occurrences of 'abc'.

If your replacement text needs to change for each matched occurrence (i.e. not simply choosing Yes/No to apply a singular replacement) you can use a Vim plugin I made called interactive-replace.

Neovim now has a feature inccommand which allows you to preview the substitution:
inccommand has two options:
set inccommand=split previews substitutions in a split pane
set inccommand=nosplit previews substitution in the active buffer
Image taken from: https://medium.com/#eric.burel/stop-using-open-source-5cb19baca44d
Documentation of the feature: https://neovim.io/doc/user/options.html#'inccommand'

Related

Limit g flag in regex substitution to part of line?

I have a file like this:
"File_name_1.dat" "File_name_1.dat"
"File_name_2.dat" "File_name_2.dat"
"Some_other_thing.dat" "Some_other_thing.dat"
Is there a regex technique can I use to replace the underscores in only the second file name on each line, like this?
"File_name_1.dat" "File name 1.dat"
"File_name_2.dat" "File name 2.dat"
"Some_other_thing.dat" "Some other thing.dat"
I tried matching the column (\%XXc in Vim), but it seems to disable the g flag.
This only replaces the first underscore after column 25:
:%s/\%25c\([^_]*\)\zs_/ /g
This only replaces the last underscore in the line:
:%s/\%25c\(.*\)\zs_/ /g
I know I could repeat that command until they're gone, but I was wondering if there is a slicker way to do it.
Yes, there is an easy way to do this with visual selections. It's convenient that your data is layed out nicely, otherwise this wouldn't work.
Visually select all of the second filenames
Run this regex:
:'<,'>s/\%V_/ /g
The \%V will restrict your substitute to the inside of the current visual selection. Here's a screen shot of what I mean:
There are probably many ways to do this. Since the data is formatted nicely I would probably visually select and delete the first column (with <c-v>), Then run :%s/_/ /g. Then paste back the first column.
If you really wanted to do this in a single regex, you would need to use a lookbehind
:%s/\(\%25c.\{-}\)\#<=_/ /g
Where \#<= matches if the preceding element matches. :help \#<=

Vim: Incsearch for replace queries

I noticed I could use regex functions with search in vim, and I could see hilights while I typed by setting incsearch. But that didn't work for search and replace queries like this one:
:%s/std::regex\s\([_a-zA-Z]*\)(/regex_t \1 = dregc(/gc
That one surprised me when it actually worked.
Are there settings or plugins for vim that, like incsearch but better, will highlight your replace query as you type? Just highlighting the matches would be pretty neat, but putting the old and new strings next to eachother in different highlighting colors would be a godsend, because I might not be sure about the backreference.
Not a direct answer to your question, but traditionally in Vim you craft your search regex first, as in:
/regex
Then you hit enter to execute it. The settings :set hlsearch and :set incsearch make this easy to see visually. Then you can just do:
:%s//replace
With no search specified, :%s (substitute acting on %, a shorctut meaning all lines in the file) will use the last search term you specified.
Going one step further, you could then do
:%s/~/replace2
Which replaces your last substitution (in this case, replace1) with replace2.
Unrelated, it may be useful for you to put this in your .vimrc:
set gdefault
Which will make all replaces global by default, so you don't need the /g flag after every :%s command.
You might be looking for vim-over?
This is a plugin that: (to clarify, let's say we're doing :%s/foo/bar/g.) i) highlights matches for substitutions in the buffer (foo) and optionally ii) previews what's after replacement (bar).

Remove text appearing after numbers in Notepad++ using regular expressions

I have a large text file which contains many timestamps. The timestamps look like this: 2013/11/14 06:52:38AM. I need to remove the last two characters (am/pm/AM/PM) from each of these. The problem is that a simple find and replace of "AM" may remove text from other parts of the file (which contains a lot of other text).
I have done a find using the regular expression (:\d\d[ap]m), which in the above example would track down the last bit of the timestamp: :38AM. I now need to replace this with :38, but I don't know how this is done (allowing for any combination of two digits after the colon).
Any help would be much appreciated.
EDIT: What I needed was to replace (:\d\d)[ap]m with \1
Make (:\d\d[ap]m) into (:\d\d)[ap]m and use $1 not \1
Go to Search > Replace menu (shortcut CTRL+H) and do the following:
Find what:
[0-9]{2}\K[AP]M
Replace:
[leave empty]
Select radio button "Regular Expression"
Then press Replace All
You can test it at regex101.
Note: the use of [0-9] is generally better than \d (read why), and avoiding to use a capture group $1 with the use of \K is considered better. It's definitely not important in your case, but it is good to know :)

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.

Multiline Regular Expression search and replace!

I've hit a wall. Does anybody know a good text editor that has search and replace like Notepad++ but can also do multi-line regex search and replace? Basically, I am trying to find something that can match a regex like:
search oldlog\(.*\n\s+([\r\n.]*)\);replace newlog\(\1\)
Any ideas?
Notepad++ can now handle multi line regular expressions (just update to the latest version - feature was introduced around March '12).
I needed to remove all onmouseout and onmouseover statements from an HTML document and I needed to create a non-greedy multi line match.
onmouseover=.?\s*".*?"
Make sure you check the: [ ] . matches newline checkbox if you want to use the multi line match capability.
EditPad Pro has better regex capabilities than any other editor I've ever used.
Also, I suspect you have an error in your regex — [\r\n.] will match only carriage returns, newlines, and full stops. If you're trying to match any character (i.e. "dot operator plus CR and LF), try [\s\S] instead.
My personal recommendation is IDM Computing's UltraEdit (www.ultraedit.com) - it can do regular expressions (both search and replace) with Perl, Unix and UltraEdit syntax. Multi-line matching is one of the capabilities in Perl regex mode in it.
It also has other nice search capabilities (e.g search in specific character column range, search in multiple files, search history, search favorites, etc...)
(source: ultraedit.com)
The Zeus editor can do multi-line search and replace.
I use Eclipse, which is free and that you may already have if you are a developer. '\R' acts as platform independent line delimiter. Here is an example of multi-line search:
search:
\bibitem.(\R.)?\R?{([^{])}$\R^([^\].[^}]$\R.$\R.)
and replace:
\defcitealias{$2}{$3}
I'm pretty sure Notepad++ can do that now via the TextFX plugin (which is included by default). Hit Control-R in Notepad++ and have a play.
TextPad has good Regex search and replace capabilities; I've used it for a while and am pretty happy with it.
From the Features:
Powerful search/replace engine using
UNIX-style regular expressions, with
the power of editor macros. Sets of
files in a directory tree can be
searched, and text can be replaced in
all open documents at once.
For more options than you could possibly need, check out "Notepad++ Alternatives" at AlternativeTo.net.
you can use Python Script plugin for Multiline Regular Expression search and replace!
- http://npppythonscript.sourceforge.net/docs/latest/scintilla.html?highlight=pymlreplace#Editor.pymlreplace
# This example replaces any <br/> that is followed by another on the next line (with optional spaces in between), with a single one
editor.pymlreplace(r"<br/>\s*\r\n\s*<br/>", "<br/>\r\n")
I use Notepad++ all the time but it's Regex has alway been a bit lacking.
Sublime Text is what you want.
EditPlus does a good job at search/replace using regex (including multiline)
You could use Visual Studio. Download Express for free if you don't have a copy.
VS's regex is non-standard, so you'd have to use \n:b+[\r\n] instead.
The latest version of UltraEdit has multiline find and replace w/ regex support.
Or if you're OK with using a more specialized regular expression tool for this, there's Regex Hero. It has the side benefit of being able to do everything on the fly. In other words, you don't have to click a button to test your regular expression because it's automatically tested after every keypress.
Personally, I'd use UltraEdit if I'm looking to replace text in multiple files. That way I can just select the files to replace as a batch and click Replace. But if I'm working with a single text file and I'm in need of writing a more complex regular expression then I'd paste it into Regex Hero and work with it there. That's because Regex Hero can save time when you see everything happen in real-time.
ED for windows has two versions of regex, three sorts of cut and paste (selection, lines or blocks, AND you can shift from one to the next (unlike ultra edit, which is clunky at best) with just a mouse click while you are highlighting -- no need to pull down a menu. The sheer speed of getting the job done is incredible, like reading on a Kindle, you don't have to think about it.
You can use a recent version of Notepad++ (Mine is 6.2.2).
No need to use the option ". match newline" as suggested in another answer. Instead, use the adequate regular expression with ^ for "begin of line" and $ for "end of line". Then use \r\n after the $ for a "new line" in a dos file (or just \n in a unix file as the carriage return is mainly used for dos/windows text file):
Ex.: to remove all lines starting with tags OBJE after a line starting with a tag UID (from a gedcom file - used in genealogy), I did use the following search regex:
^UID (.*)$\r\n^(OBJE (.*)$\r\n)+
And the following replace value:
UID \1\r\n
This is matching lines like this:
UID 4FBB852FB485B2A64DE276675D57A1BA
OBJE #M4#
OBJE #M3#
OBJE #M2#
OBJE #M1#
and the output of the replacement is
UID 4FBB852FB485B2A64DE276675D57A1BA
550 instances have been replaced in less than 1 sec. Notepad++ is really efficient!
Otherwise, to validate a Regular expression I like to use the .Net RegEx Tester (http://regexhero.net/tester/). It's really great to write and test on the fly a Reg Ex...
PS.: Also, you can use [\s\S] in your regex to match any character including new lines. So, if you look for any block of "multi-line" text starting with "xxx" and ending with "abc", the following Regex will be fine:^xxx[\s\S]*?abc$ where "*?" is to match as less as possible between xxx and abc !!!