How do I find and replace string of # (pound) characters in vim? - vim

I have a file where I have comments like ######### Utility Functions #######. I am trying to clean it up and make it something like # Utility Functions # which requires me to match a string of more than one pound signs and replace it with a single pound sign.
I have tried the following
:%s/#+/#/gc
:%s/"#"+/#/gc
:%s/\#+/#/gc
:%s/(#)+/#/gc
and a bunch more. As I understand # has a special significance to match multiple characters like * but in reverse direction. This would mean that I would have to escape it somehow to achieve the above. Any help appreciated.

try that: :%s/\v#{2,}/#/g
#{2,} " 2, means at least two
There is a shortcut for "more than one" in most regex flavours: + so
:%s/\v#+/#/g
works too, if you use "very magic" (\v), see :h magic.

No, # has no special meaning, and + as you use it is just a regular +. You need to escape the + to make it a "multi":
:%s/#\+/#/g
See :help multi.

You can try using quotes.
sed 's/"#"//g'

Related

Substitute in vim, with special characters

I am trying to use substitute command in vim to enclose all occurences of a particular pattern
\cite{author1}
\cite{author2}
with
(\cite{author1})
(\cite{author2})
Based on other answers in stack exchangeI used the following vim command
%s/\\cite{(\w\+)}/(\\cite{\1})/g
But, no luck. It says "no matches found". I put two back slashes, one of which is supposed to be the escape character. Kindly help.
I know I could use some other editor and finish the job, but I want to know my mistake. Thank you.
please escape ()
%s/\\cite{\(\w\+\)}/(\\cite{\1})/g
You do not need a capture group to get the entire match. You can use \0 or & for the whole match in the replacement portion of your substitution.
:%s/\\cite{\w\+}/(&)/g
If you do want to use a capture group, then you need to escape the capture group/parenthesis.
:%s/\(foo\)/(\1)/g
For more help see:
:h :s%
:h /magic
As mentioned, normally you need escape the parentheses.
You can use very magic mode (\v) to make the regex simpler; removing the need to escape lots of the regex parts, including the parentheses for capturing:
%s/\v(\\cite\{\w+\})/(\1)/g
Knowing what every sign in a regular expression does in vim is sometimes very
difficult, especially for all the modes and configuration variables that this
depends on. For that reason, it is very important to have visual feedback about
what text are we really matching in any moment while crafting regular
expressions.
If you work with neovim, there is a special option called inccommand that you
can enable to live preview the matches and substitution. That way you can figure
out you errors more quickly. This feature is very likely to be included also in
vim in the future, but independently of that, you can also use simple vim to
give you visual feedback if you enable the option incsearch.
With incsearch set, you can watch the matches of / and ? while you write them
just to be sure that the pattern is correct. Later you can exploit a nice
feature from the substitution: if you leave the first section empty, the last
search will be used.
So you could first make the search:
/\\cite{\w\+}/(&)/g
In the meantime, vim will be showing you the matched text visually. Once you
are sure that the pattern is correct press enter, and finally type:
:%s//(\1)<Enter>
Also, in case you want something more powerful than this simple hack, you can go
for my plugin Extend.vim, that can
do that and much more with great visual feedback.

How to efficiently switch arguments in vim

I come upon one scenario when editing a file in vim and I still haven't found a way to do it quickly in vim way. When editing a call of a function, I offently put my arguments in a wrong order.
anyFunction(arg2, arg1)
When arriving on this situation, I have to find arg2 / delete it / append it before the ')' / deal with the ', ' / etc.
Isn't it a better way to this task quickly ? I am open to any idea (macro/ shortcut / plugin) even if I'd rather have a 'vim only' way of doing this
You need two things:
A text object to quickly select an argument (as they aren't always that simple like in your example). argtextobj plugin (my improved fork here) does this.
Though you can use delete + visual mode + paste + go back + paste, a plugin to swap text makes this much easier. My SwapText plugin or the already mentioned exchange plugin both do that job.
put this mapping in your _vimrc.
" gw : Swap word with next word
nmap <silent> gw :s/\(\%#\w\+\)\(\_W\+\)\(\w\+\)/\3\2\1/<cr><c-o><c-l>
then in normal mode with the cursor anywhere in arg1 type gw to swap parameters
anyFunction(arg1, arg2)
Explanation:-
arg1 the separator (here a comma) and arg2 are put into regexp memories 1 2 3
the substitute reverses them to 3 2 1
Control-O return to last position
Control-L redraw the screen
Note that the separator is any non-alphanumeric character or string e,g whitespace
I actually made a plugin to deal with a exact situation called argumentative.vim. (Sorry for the plug.)
Argumentative.vim provides the following mappings:
[, and ], motions which will go to the previous or next argument
<, and >, to shift an argument left or right
i, and a, argument text objects. e.g. da,, ci, or yi,
So with this plugin you move to the argument in question and then do a <, or >, as many times as needed. It can also take a count e.g. 2>,.
If you have Tim Pope's excellent repeat.vim plugin installed <, and >, become repeatable with the . command.
I would recommend a plugin: vim-exchange for that:
https://github.com/tommcdo/vim-exchange
This is a perfect use for a regular expression search and replace.
You want to find "anyFunction(", then swap anything up to the ',' with anything from the ',' to the ')'. This is fairly straightforward, using [^,]* for "anything up to the ','" and [^)]* for "anything up to the ')'". Use \(...\) to capture each thing, and \1, \2 to refer to those things in the replacement:
:s#anyFunction(\s*\([^,]*\),\s*\([^)]*\)#anyFunction(\2, \1#g
Note how I use \s* to allow any whitespace between the "anyFunction(" and the first thing, and also between the ',' and the second thing.
If you want this to be able to span multiple lines, you can use \_s instead of \s, and capture the whitespace if you want to maintain the multi-line format:
:s#anyFunction(\(\_s*\)\([^,]*\),\(\_s*\)\([^)]*\)#anyFunction(\1\4,\3\2#g
There is also a multi-line variant of [...] collections, for example \_[^,] meaning "anything (even a new line) except for a ',' " which you could use in the pattern if your use case demands it.
For details, consult the help topics for: /\s, /\_s, /\1, /\(, and /[.
If you want a more general-purpose mapping to use at every location, you can use the cursor position in your regular expression, rather than keying off the function name. The cursor position in a regular expression is matched using \%# as demonstrated here: http://vim.wikia.com/wiki/Exchanging_adjacent_words
Similar to what Peter Rincker suggested (Argumentative), sideways also does what you describe.

Vi search and replace with slashes

I am trying to run this command in vi
:s/href="\//href="http:\/\/website.com\/folder\/subfolder\//g
but got this error E486: Pattern not found: href="\/
What am i doing wrong?
That error means pretty much what it says. vi didn't find any pattern href="/ (ignoring escapes) in your file.
Sometimes it's easier to use something besides / for the search delimiter if your search has a lot of slashes, so you don't need to escape them all. Try replacing the / delimiter with # instead, like this:
s#href="/#href="http://website.com/folder/subfolder/#g
Then maybe you can more easily see what's wrong with your pattern:
becouse there are many '/' chars, try use another delimiter, ex ',':
:s,some/pattern/with/slashes,new/string,g
On another note. That substition worked for me. Just copied and pasted. Are you on the same line that you are trying to perform the substitution on? the 'g' is meant globally on the line you are on. If you need to perform the search and replace on the file the use :%s/

Vim Search/replace: what do I need to escape?

I'm trying to search and replace $data['user'] for $data['sessionUser'].
However, no matter what search string I use, I always get a "pattern not found" as the result of it.
So, what would be the correct search string? Do I need to escape any of these characters?
:%s/$data['user']/$data['sessionUser']/g
:%s/\$data\[\'user\'\]/$data['sessionUser']/g
I did not test this, but I guess it should work.
Here's a list of all special search characters you need to escape in Vim: `^$.*[~)+/
There's nothing wrong with with the answers given, but you can do this:
:%s/$data\['\zsuser\ze']/sessionUser/g
\zs and \ze can be used to delimit the part of the match that is affected by the replacement.
You don't need to escape the $ since it's the at the start of the pattern and can't match an EOL here. And you don't need to escape the ] since it doesn't have a matching starting [. However there's certainly no harm in escaping these characters if you can't remember all the rules. See :help pattern.txt for the full details, but don't try to digest it all in one go!
If you want to get fancy, you can do:
:%s/$data\['\zsuser\ze']/session\u&/g
& refers to the entire matched text (delimited by \zs and \ze if present), so it becomes 'user' in this case. The \u when used in a replacement string makes the next character upper-case. I hope this helps.
Search and replace in vim is almost identical to sed, so use the same escapes as you would with that:
:%s/\$data\['user'\]/$data['session']/g
Note that you only really need to escape special characters in the search part (the part between the first set of //s). The only character you need to escape in the replace part is the escape character \ itself (which you're not using here).
The [ char has a meaning in regex. It stands for character ranges. The $ char has a meaning too. It stands for end-line anchor. So you have to escape a lot of things. I suggest you to try a little plugin like this or this one and use a visual search.

In vim, is there a plugin to use % to match the corresponding double quote (")?

The % key is one of the best features of vim: it lets you jump from { to }, [ to ], and so on.
However, it does not work by default with quotes: Either " or ', probably because the opening and closing quote are the same character, making implementation more difficult.
Thinking a bit more about the problem, I'm convinced that it should be implemented, by counting if the number of preceding quotes is odd or even and jumping to the previous or next quote, accordingly.
Before I try to implement it myself, I'd just like to know if someone already has?
Depending on your reason for needing this, there may be a better way to accomplish what you're looking for. For example, if you have the following code:
foo(bar, "baz quux")
^
and your cursor happens to be at the ^, and you want to replace everything inside the quotes with something else, use ci". This uses the Vim "text objects" to change (c) everything inside (i) the quotes (") and puts you in insert mode like this:
foo(bar, "")
^
Then you can start typing the replacement text. There are many other text objects that are really useful for this kind of shortcut. Learn (and use) one new Vim command per week, and you'll be an expert in no time!
Greg's answer was very useful but i also like the 'f' and 'F' commands that move the cursor forward and backward to the character you press after the command.
So press f" to move to the next " character and F" to move to the previous one.
I have found this technique very useful for going to the start/end of a very long quoted string.
when cursor is inside the string, visually select the whole string using vi" or vi'
go to start/end of the string by pressing o
press escape to exit visual select mode
this actually takes the cursor next to the start/end quote character, but still feels pretty helpful.
Edit
Adding Stefan's excellent comment here which is a better option for anyone who may miss the comment.
If you use va" (and va') then it will actually visually select the quotes itself as well.
– Stefan van den Akker
I'd like to expand on Greg's answer, and introduce the surround.vim plugin.
Suppose that rather than editing the contents of your quotes, you want to modify the " characters themselves. Lets say you want to change from double-quotes to single-quotes.
foo(bar, "baz quux")
^
The surround plugin allows you to change this to
foo(bar, 'baz quux')
^
just by executing the following: cs"' (which reads: "change the surrounding double-quotes to single-quotes").
You could also delete the quote marks simply by running: ds" (which reads: "delete the surrounding double-quotes).
There is a good introduction to the surround plugin here.
I know this question is old but here is a plugin to use % to match the corresponding double quote:
https://github.com/airblade/vim-matchquote

Resources