How to replace the strings (4000 to 4200 ) to (5000 to 5200) in vim ..
Another possibility:
:%s/\v<4([01]\d{2}|200)>/5\1/g
This one does 200 as well, and it does not suffer from the "leaning toothpick syndrome" too much since it uses the \v switch.
EDIT #1: Added word boundary anchors ('<' and '>') to prevent replacing "14100" etc.
EDIT #2: There are cases where a "word boundary" is not enough to correctly capture the wanted pattern. If you want white space to be the delimiting factor, the expression gets somewhat more complex.
:%s/\v(^|\s)#<=4([01]\d{2}|200)(\s|$)#=/5\1/g
where "(^|\s)#<=" is the look-behind assertion for "start-of-line" or "\s" and "(\s|$)#=" is the look-ahead for "end-of-line" or "\s".
:%s/\<4\([01][0-9][0-9]\)\>/5\1/g
:%s/\<4\([0-1][0-9][0-9]\)\>/5\1/g
will do 4000 to 4199. You would have to then do 4200/5200 separately.
A quick explanation. The above finds 4, followed by 0 or 1, followed by 0-9 twice. The 0-1,0-9,0-9 are wrapped in a group, and the replacement (following the slash) says replace with 5 followed by the last matched group (\1, i.e. the bit following the 4).
\< and > are word boundaries, to prevent matching against 14002 (thx Adrian)
% means across all lines. /g means every match on the line (not just the first one).
If you didn't want to do a full search and replace for some reason, remember that ctrl-a will increment the next number below or after the cursor. So in command mode, you could hit 1000 ctrl-a to increase the next number by 1000.
If you're on Windows, see an answer in this question about how to make ctrl-a increment instead of select all.
More typing, but less thinking:
:%s/\d\+/\=submatch(0) >= 4000 && submatch(0) <= 4200 ? submatch(0) + 1000 : submatch(0)/g
Related
I'm trying to search for only a singular digit in vim by itself. For example, if there are two sets of digits 1 and 123 and I want to search for 1, I would only want the singular 1 digit to be found.
I have tried using regular expressions like \<1> and \%(a)#
You almost had the right solution. You want:
\<1\>
This is because each angled bracket needs to be escaped. Alternatively, you could use:
\v<1>
The \v flag tells vim to treat more characters as special without needing to be escaped (for example, (){}+<> all become special rather than literal text. Read :h /\v for more on this.
A great reference for learning regex in vim is vimregex.com. The \<\> characters are explained in 4.1 "Anchors".
If you want to match text like 1.23 this is possible too. Two different approaches:
Modify the iskeyword option so that it includes .. This will also affect how w moves
Use \v<1(\d|.)#!, which basically means "a 1 at the beginning of a word, that isn't followed by some other digit or a period."
Please let me know, How I can remove the last word from each line using vim commands?
Before :
abcdef 123
xyz 1256
qwert 2
asdf 159
after :
abcdef
xyz
qwert
asdf
Similarly please let me know how to remove the second word from each line using vim command?
Use the following regex (in ex mode):
%s/\s*\w\+\s*$//
This tells it to find optional whitespace, followed by one or more word characters, followed by optional whitespace, followed by end of line—then replace it with nothing.
The question's been answered already, but here's what I'd more likely end up doing:
Record a macro:
qq to record a macro into register "q"
$ to go to the end of the line
daw to delete a word
q to stop recording
Then select the rest of the lines:
j to go down a line
vG to select to the end of the file
And apply the macro:
:norm #q
Some similar alternatives:
:%norm $daw
qq$dawjq (note the added j) then 999#q to replay the macro many times. (Macro execution stops at the first "error" -- in this case, you'd probably hit the bottom of the file, j would not work, and the macro would stop.)
The key for this is the :substitute command; it is very powerful (and often used in vi / Vim).
You need to come up with a regular expression pattern that matches what you want to delete. For the last word, that's whitespace (\s), one or more times \+ (or any number (*), depending on how you want to treat single-word lines), followed by word characters (\w\+), anchored to the end of the line ($). Note that word has a special meaning in Vim; you may want to use a different atom (e.g. \S). Voila:
:%s/\s\+\w\+$//
For the second word, you can make use of the special \zs and \ze atoms that assert for matches, but do not actually match: Anchored at the start (^), match a word, then start the match for a second one:
:%s/^\w\+\s\+\zs\w\+\s\+//
Soon, you'll also want to reorder things, not just remove them. For that, you need to know capturing groups: \(...\). The text matched by those can then be referred to in the replacement part. For example, to swap the first and second words:
:%s/^\(\w\+\s\+\)\(\w\+\s\+\)/\2\1/
For details, have a look at the help, especially :help :substitute and :help pattern.
To remove the second word from the start of a line, use the following:
:%s/^\(\s*\w\+\s\+\)\w\+\s*/\1/
Update
To treat special characters as part of the word, you have to use the \S (which matches all non-whitespace characters) instead of \w (which matches only word characters [0-9A-Za-z_]). Then, the command would be:
:%s/^\(\s*\S\+\s\+\)\S\+\s*/\1/
I have the following string in the code at multiple places,
m_cells->a[ Id ]
and I want to replace it with
c(Id)
where the string Id could be anything including numbers also.
A regular expression replace like below should do:
%s/m_cells->a\[\s\(\w\+\)\s\]/c(\1)/g
If you wish to apply the replacement operation on a number of files you could use the :bufdo command.
Full explanation of #BasBossink's answer (as a separate answer because this won't fit in a comment), because regexes are awesome but non-trivial and definitely worth learning:
In Command mode (ie. type : from Normal mode), s/search_term/replacement/ will replace the first occurrence of 'search_term' with 'replacement' on the current line.
The % before the s tells vim to perform the operation on all lines in the document. Any range specification is valid here, eg. 5,10 for lines 5-10.
The g after the last / performs the operation "globally" - all occurrences of 'search_term' on the line or lines, not just the first occurrence.
The "m_cells->a" part of the search term is a literal match. Then it gets interesting.
Many characters have special meaning in a regex, and if you want to use the character literally, without the special meaning, then you have to "escape" it, by putting a \ in front.
Thus \[ and \] match the literal '[' and ']' characters.
Then we have the opposite case: literal characters that we want to treat as special regex entities.
\s matches white*s*pace (space, tab, etc.).
\w matches "*w*ord" characters (letters, digits, and underscore _).
(. matches any character (except a newline). \d matches digits. There are more...)
If a character is not followed by a quantifier, then exactly one such character matches. Thus, \s will match one space or tab, but not fewer or more.
\+ is a quantifier, and means "one or more". (\? matches 0 or 1; * (with no backslash) matches any number: zero or more. Warning: matching on zero occurrences takes a little getting used to; when you're first learning regexes, you don't always get the results you expected. It's also possible to match on an arbitrary exact number or range of occurrences, but I won't get into that here.)
\( and \) work together to form a "capturing group". This means that we don't just want to match on these characters, we also want to remember them specially so that we can do something with them later. You can have any number of capturing groups, and they can be nested too. You can refer to them later by number, starting at 1 (not 0). Just start counting (escaped) left-parantheses from the left to determine the number.
So here, we are matching a space followed by a group (which we will capture) of at least one "word" character followed by a space, within the square brackets.
Then section between the second and third / is the replacement text.
The "c" is literal.
\1 means the first captured group, which in this case will be the "Id".
In summary, we are finding text that matches the given description, capturing part of it, and replacing the entire match with the replacement text that we have constructed.
Perhaps a final suggestion: c after the final / (doesn't matter whether it comes before or after the 'g') enables *c*onfirmation: vim will highlight the characters to be replaced and will show the replacement text and ask whether you want to go ahead. Great for learning.
Yes, regexes are complicated, but super powerful and well worth learning. Once you have them internalized, they're actually fairly easy. I suggest that, as with learning vim itself, you start with the basics, get fluent in them, and then incrementally add new features to your repertoire.
Good luck and have fun.
When you try to remove html tags from a line, one possible way of doing it, is to use the :s command and write a regex that understands the beginning and the end of a tag at the same time. My go for it was:
:s %</?center>%%g
But this way, vim says it doesn't find anything. So I had to use the following instead, which worked:
:s %</*center>%%g
Why is that one works but the other doesn't? Shouldn't ? say "the character before can come once or maybe not at all"?
You need to escape ? with \.
Refer help-page:
:h pattern-overview
They aren't the same.
The ? (question mark) matches the preceding character 0 or 1 times
only, for example, colou?r will find both color (0 times) and colour
(1 time).
The * (asterisk or star) matches the preceding character 0 or more
times, for example, tre* will find tree (2 times) and tread (1 time)
and trough (0 times).
Can you give us the matches that will be substituted?
Moreover, i know that this kind of operation is done with that command s/foo/bar/g that will substitute every occurency of foo with bar
If you want to use ? like this to have to use vim's very magic regex mode (\v), however this also interprets < and > as word boundaries so now they need to be escaped:
:%s,\v\</?center\>,,g
The shorter option here, as you have discovered, is to escape the ?:
:%s,</\?center>,,g
See :help /magic for more.
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.