Highlight keyword only on specific lines - vim

Sometimes I just want to highlight the keyword on specific lines. Since the keyword is really common, it can appear everywhere in the file.
For instance, I'm searching for 1s on lines starting with check in the following file:
...
[block-1]
test 31 for instruction block1_test
stim 011000011100101
check xxxxx1xxxx1xxxx
...
Using /1 will highlight every 1, and makes it a bit annoying to find the one I want.
Though using /^check\>.*1 narrowers the search result, it matchs from the very beginning to the last 1 on that line.
I'd like to make all the 1s on check lines clearer to see, to find. Can I achieve this?

You can use a look-behind operator \#<= in your pattern to match 1 but only in lines that start with check.
This search pattern does what you requested:
/\(^check\>.*\)\#<=1
Using "very magic" option :h magic:
/\v(^check .*)#<=1

Related

vim Search Replace should use replaced text in following searches

I have a data file (comma separated) that has a lot of NAs (It was generated by R). I opened the file in vim and tried to replace all the NA values to empty strings.
Here is a sample slimmed down version of a record in the file:
1,1,NA,NA,NA,NATIONAL,NA,1,NANA,1,AMERICANA,1
Once I am done with the search-replace, the intended output should be:
1,1,,,,NATIONAL,,1,NANA,1,AMERICANA,1
In other words, all the NAs should be replaced except the words NATIONAL, NANA and AMERICANA.
I used the following command in vim to do this:
1, $ s/\,NA\,/\,\,/g
But, it doesn't seem to work. Here is the output that I get:
1,1,,NA,,NATIONAL,,1,NANA,1,AMERICANA,1
As you can see, there is one ,NA, that is left out of the replacement process.
Does anyone have a good way to fix it? Thanks.
A trivial solution is to run the same command again and it will take care of the remaining ,NA,. However, it is not a feasible solution because my actual data file has 100s of columns and 500K+ rows each with a variable number of NAs.
, doesn't have a special meaning so you don't have to escape it:
:1,$s/,NA,/,,/g
Which doesn't solve your problem.
You can use % as a shorthand for 1,$:
:%s/,NA,/,,/g
Which doesn't solve your problem either.
The best way to match all those NA words to the exclusion of other words containing NA would be to use word boundaries:
:%s/,\<NA\>,/,,/g
Which still doesn't solve your problem.
Which makes those commas, that you used to restrict the match to NA and that are causing the error, useless:
:%s/\<NA\>//g
See :help :range and :help \<.
Use % instead of 1,$ (% means "the buffer" aka the whole file).
You don't need \,. , works fine.
Vim finds discrete, non-overlapping matches. so in ,NA,NA,NA, it only finds the first ,NA, and third ,NA, as the middle one doesn't have its own separate surrounding ,. We can modify the match to not include certain characters of our regex with \zs (start) and \ze (end). These modify our regex to find matches that are surrounded by other characters, but our matches don't actually include them, so we can match all the NA in ,NA,NA,NA,.
TL;DR: %s/,\zsNA\ze,//g

Find and replace only part of a single line in Vim

Most substitution commands in vim perform an action on a full line or a set of lines, but I would like to only do this on part of a line (either from the cursor to end of the line or between set marks).
example
this_is_a_sentence_that_has_underscores = this_is_a_sentence_that_should_not_have_underscores
into
this_is_a_sentence_that_has_underscores = this is a sentence that should not have underscores
This task is very easy to do for the whole line :s/_/ /g, but seems to be much more difficult to only perform the replacement for anything after the =.
Can :substitution perform an action on half of a line?
Two solutions I can think of.
Option one, use the before/after column match atoms \%>123c and \%<456c.
In your example, the following command substitutes underscores only in the second word, between columns 42 and 94:
:s/\%>42c_\%<94c/ /g
Option two, use the Visual area match atom \%V.
In your example, Visual-select the second long word, leave Visual mode, then execute the following substitution:
:s/\%V_/ /g
These regular expression atoms are documented at :h /\%c and :h /\%V respectively.
Look-around
There is a big clue your post already:
only perform the replacement for anything after the =.
This often means using a positive look-behind, \#<=.
:%s/\(=.*\)\#<=_/ /g
This means match all _ that are after the following pattern =.*. Since all look-arounds (look-aheads and look-behinds) are zero width they do not take up space in the match and the replacement is simple.
Note: This is equivalent to (?<=...) in perl speak. See :h perl-patterns.
What about \zs?
\zs will set the start of a match at a certain point. On the face this sounds exactly what is needed. However \zs will not work correctly as it matches the pattern before the \zs first then the following pattern. This means there will only be one match. Look-behinds on the other hand match the part after \#<= then "look behind" to make sure the match is valid which makes it great for multiple replacement scenario.
It should be noted that if you can use \zs not only is it easy to type but it is also more efficient.
Note: \zs is like \K in perl speak.
More ways?!?
As #glts mentioned you can use other zero-width atoms to basically "anchor" your pattern. A list of a few common ways:
\%>a - after the 'a mark
\%V - match inside the visual area
\%>42c - match after column 42
The possible downside of using one of these methods they need you to set marks or count columns. There is nothing wrong with this but it means the substitution will maybe affected by side-effects so repeating the substitution may not work correctly.
For more help see:
:h /\#<=
:h /zero-width
:h perl-patterns
:h /\zs

VIM how to substitute with offset

The search command in vim allows you to place the cursor relative to the search results. For example, /hello/b+2 places the cursor on the first l.
How do I do that with the substitute command?
s/hello/b+2/_/
does not work.
I need this to replace not the entire search string, but a portion of it only (specifically, to blank out all but the first character of a word).
You generally have two options: similar to other regex engines zero-width matches (though with different syntax):
:s/\(he\)\#<=llo/_/
or vim-specific “set the start of the match here”:
:s/he\zsllo/_/
. Also, there is a workaround which will look similar in almost every other regex engine:
:s/\(he\)llo/\1_/
: this captures text that should be unchanged and makes replacement include it.

Search for string and get count in vi editor

I want to search for a string and find the number of occurrences in a file using the vi editor.
THE way is
:%s/pattern//gn
You need the n flag. To count words use:
:%s/\i\+/&/gn
and a particular word:
:%s/the/&/gn
See count-items documentation section.
If you simply type in:
%s/pattern/pattern/g
then the status line will give you the number of matches in vi as well.
:%s/string/string/g
will give the answer.
(similar as Gustavo said, but additionally: )
For any previously search, you can do simply:
:%s///gn
A pattern is not needed, because it is already in the search-register (#/).
"%" - do s/ in the whole file
"g" - search global (with multiple hits in one line)
"n" - prevents any replacement of s/ -- nothing is deleted! nothing must be undone!
(see: :help s_flag for more informations)
(This way, it works perfectly with "Search for visually selected text", as described in vim-wikia tip171)
:g/xxxx/d
This will delete all the lines with pattern, and report how many deleted. Undo to get them back after.
Short answer:
:%s/string-to-be-searched//gn
For learning:
There are 3 modes in VI editor as below
: you are entering from Command to Command-line mode. Now, whatever you write after : is on CLI(Command Line Interface)
%s specifies all lines. Specifying the range as % means do substitution in the entire file. Syntax for all occurrences substitution is :%s/old-text/new-text/g
g specifies all occurrences in the line. With the g flag , you can make the whole line to be substituted. If this g flag is not used then only first occurrence in the line only will be substituted.
n specifies to output number of occurrences
//double slash represents omission of replacement text. Because we just want to find.
Once got the number of occurrences, you can Press N Key to see occurrences one-by-one.
For finding and counting in particular range of line number 1 to 10:
:1,10s/hello//gn
Please note, % for whole file is repleaced by , separated line numbers.
For finding and replacing in particular range of line number 1 to 10:
:1,10s/helo/hello/gn
use
:%s/pattern/\0/g
when pattern string is too long and you don't like to type it all again.
I suggest doing:
Search either with * to do a "bounded search" for what's under the cursor, or do a standard /pattern search.
Use :%s///gn to get the number of occurrences. Or you can use :%s///n to get the number of lines with occurrences.
** I really with I could find a plug-in that would giving messaging of "match N of N1 on N2 lines" with every search, but alas.
Note:
Don't be confused by the tricky wording of the output. The former command might give you something like 4 matches on 3 lines where the latter might give you 3 matches on 3 lines. While technically accurate, the latter is misleading and should say '3 lines match'. So, as you can see, there really is never any need to use the latter ('n' only) form. You get the same info, more clearly, and more by using the 'gn' form.

Vim: need help with a tiny script code to highlight

I need a script code to highlight "[Capítulo" and "]" and everything between them. Thank you.
I want it to work everytime I open , for example, a .txt file. Just like code highlighting.
Here's an easy way to do it:
in vim, make sure syntax highlighting is on with :syn on
run the command :highlight to get a listing of all the highlight group names, and samples of what they look like. The Error group looks like it stands out well in my colorscheme, so I'll use that in my example (but you can use any of the other names, like Todo or Search)
:syntax match Error /\[Capítulo[^\]]*\]/
This pattern will keep you from greedily matching the largest chunk. Even though other people are suggesting you use the regular expression /\[Capítulo.*\]/ - it's probably not what you want, because it will match everything in between if there are two or more such patterns on a line.
For example /\[Capítulo.*\]/ will match this entire line:
[Capítulo foo] these words should not be highlighted [Capítulo bar]
The same example but with /\[Capítulo[^\]]*\]/ will only match stuff inside []:
[Capítulo foo] these words should not be highlighted [Capítulo bar]
With regular expressions, it's a common trick to make a group that matches everything but the character that you want to end your match, instead of using the .* which will match as many characters as it can. In this case, we make the group [^\]]* - which says "match everything except ]."
If this works the way you want it to, add the syntax match line without the ":" to your .vimrc
A regular expression is what you're looking for:
Type / to enter in "search mode" and type:
\[Capítulo.*\]/

Resources