ChatGPT解决这个技术问题 Extra ChatGPT

Find and replace strings in vim on multiple lines

I can do :%s/<search_string>/<replace_string>/g for replacing a string across a file, or :s/<search_string>/<replace_string>/ to replace in current line.

How can I select and replace words from selective lines in vim?

Example: replace text from lines 6-10, 14-18 but not from 11-13.


C
Cine

Replace All:

:%s/foo/bar/g

Find each occurrence of 'foo' (in all lines), and replace it with 'bar'.

For specific lines:

:6,10s/foo/bar/g

Change each 'foo' to 'bar' for all lines from line 6 to line 10 inclusive.


what is the purpose of /g here? Sorry I'm new to linux
@RajaAnbazhagan The final part of this expression, after the last /, is where you indicate flags for the operation. This command will normally replace the first match on a line; With the g flag it will replace all occurrences.
You should really reference your sources (i.e, vim.wikia.com/wiki/Search_and_replace), if you are going to copy and past another person's work.
The % thing does the work! Otherwise, it's just only the first occurrence.
% => run this command on all lines. g => match multiple occurences in the same line.
I
Ingo Karkat

The :&& command repeats the last substitution with the same flags. You can supply the additional range(s) to it (and concatenate as many as you like):

:6,10s/<search_string>/<replace_string>/g | 14,18&&

If you have many ranges though, I'd rather use a loop:

:for range in split('6,10 14,18')| exe range 's/<search_string>/<replace_string>/g' | endfor

Thanks. Note for future users - :6,10s/<search_string>/<replace_string>/g | :14,18&& | :20,23&& | :28,31&& will also work, for loop makes it more easy to remember and execute.
Glad you like it! The : on the subsequent commands is optional, btw, so you can save some more keystrokes.
:&& will save me hundreds of keystrokes per week. Thanks!
It works without the 'g' at the end in my vim. So maybe when you specify the line range it doesn't need global flag
@TayyarR The range covers the lines (vertically, so to speak), while the 'g' flag determines whether only one or all matches within the line (so horizontally) are replaced.
A
Attila O.

As a side note, instead of having to type in the line numbers, just highlight the lines where you want to find/replace in one of the visual modes:

VISUAL mode (V)

VISUAL BLOCK mode (Ctrl+V)

VISUAL LINE mode (Shift+V, works best in your case)

Once you selected the lines to replace, type your command:

:s/<search_string>/<replace_string>/g

You'll note that the range '<,'> will be inserted automatically for you:

:'<,'>s/<search_string>/<replace_string>/g

Here '< simply means first highlighted line, and '> means last highlighted line.

Note that the behaviour might be unexpected when in NORMAL mode: '< and '> point to the start and end of the last highlight done in one of the VISUAL modes. Instead, in NORMAL mode, the special line number . can be used, which simply means current line. Hence, you can find/replace only on the current line like this:

:.s/<search_string>/<replace_string>/g

Another thing to note is that inserting a second : between the range and the find/replace command does no harm, in other words, these commands will still work:

:'<,'>:s/<search_string>/<replace_string>/g
:.:s/<search_string>/<replace_string>/g

> Example: replace text from lines 6-10, 14-18 but not from 11-13. — doesn't your reply answer this very question, does it?
This is a great answer to do it visually instead of noting down the line numbers , thanks :)
C
Community

Search and replace

:%s/search\|search2\|search3/replace/gci

g => global search

c => Ask for confirmation first

i => Case insensitive

If you want direct replacement without confirmation, use below command

:%s/search/replace/g

If you want confirmation for each replace then run the below command

:%s/search/replace/gc

Ask for confirmation first, here search will be case insensitive.

:%s/search/replace/gci

S
Stephan

You can do it with two find/replace sequences

  :6,10s/<search_string>/<replace_string>/g
  :14,18s/<search_string>/<replace_string>/g

The second time all you need to adjust is the range so instead of typing it all out, I would recall the last command and edit just the range


S
SMJ

In vim if you are confused which all lines will be affected, Use below

 :%s/foo/bar/gc  

Change each 'foo' to 'bar', but ask for confirmation first. Press 'y' for yes and 'n' for no. Dont forget to save after that

:wq

You can actually use the c flag in addition to specifying the range, so :6,10s/<search_string>/<replace_string>/c works. c stands for confirm. I use the c flag quite often to prevent from accidentally replacing words where I didn't thought about that they exist there as well.
G
Gaurav Gandhi

VI search and replace command examples

Let us say you would like to find a word called “foo” and replace with “bar”.

First hit [Esc] key

Type : (colon) followed by %s/foo/bar/ and hit [Enter] key

:%s/foo/bar/


Your :%s/<search_string>/<replace_string>/g command will replace all occurrences in the whole file. Not exactly the answer to the question, but useful nonetheless :)
@tanius Actually it was the most straight forward answer to my problem. You can consider modifying the question to "Find and replace strings in vim on "Selected" lines"
l
lingjiankong

We don't need to bother entering the current line number.

If you would like to change each foo to bar for current line (.) and the two next lines (+2), simply do:

:.,+2s/foo/bar/g

If you want to confirm before changes are made, replace g with gc:

:.,+2s/foo/bar/gc

Another nice thing that I often use is :.,$s/foo/bar/gc to search&replace starting from the current line up to the end of the file.
S
Saul Axel Martinez Ortiz

Specifying the range through visual selection is ok but when there are very simple operations over just a couple of lines that can be selected by an operator the best would be to apply these commands as operators.

This sadly can't be done through standards vim commands. You could do a sort of workaround using the ! (filter) operator and any text object. For example, to apply the operation to a paragraph, you can do:

!ip

This has to be read as "Apply the operator ! inside a paragraph". The filter operator starts command mode and automatically insert the range of lines followed by a literal "!" that you can delete just after. If you apply this, to the following paragraph:

1
2  Repellendus qui velit vel ullam!
3  ipsam sint modi! velit ipsam sint
4  modi! Debitis dolorum distinctio
5  mollitia vel ullam! Repellendus qui
6  Debitis dolorum distinctio mollitia
7  vel ullam! ipsam
8
9  More text around here

The result after pressing "!ap" would be like:

:.,.+5

As the '.' (point) means the current line, the range between the current line and the 5 lines after will be used for the operation. Now you can add the substitute command the same way as previously.

The bad part is that this is not easier that selecting the text for latter applying the operator. The good part is that this can repeat the insertion of the range for other similar text ranges (in this case, paragraphs) with sightly different size. I.e., if you later want to select the range bigger paragraph the '.' will to it right.

Also, if you like the idea of using semantic text objects to select the range of operation, you can check my plugin EXtend.vim that can do the same but in an easier manner.


Z
ZhaoGang

To answer this question:

:40,50s/foo/bar/g

replace foo with bar in these lines between the 40th line and the 50th line(inclusive), when execute this command you can currently in any line.

:50,40s/foo/bar/g

also works, vim will ask you for comfirm and then do the replacement for you as if you have input the first command.

:,50s/foo/bar/g

replace foo with bar in these lines between the line you are currently in and the 50th line(inclusive). (if you are in a line AFTER the 50th line vim will ask for confirm again)

To clearity the difference between vim and the vrapper plugin of Eclipse:

Note that in varpper

:,50s/foo/bar/g command will NOT work.

:50,40s/foo/bar/g will work without asking for comfirmation.

(For Vrapper Version 0.74.0 or older).


M
Martin Tournoij
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal

Suppose if you want to replace the above with some other info.

COMMAND(:%s/\/sys\/sim\/source\/gm\/kg\/jl\/ls\/owow\/lsal/sys.pkg.mpu.umc.kdk./g)

In this the above will be get replaced with (sys.pkg.mpu.umc.kdk.) .


I'm not sure this actually answers the question. From the question it appears the person asking is already aware of how to use %s to modify input but wants to know how to do it "semi-globally" (i.e. his specification is lines 6-10 and 14-18 but not on lines 11-13).
Also what is "COMMAND"? And you're suffering from leaning toothpick syndrome.
To cure that syndrome, you can use another character as delimiter instead of the default /, e.g. !, @, _ : :%s_/sys/sim/source/gm/kg/jl/ls/owow/lsal_sys.pkg.mpu.umc.kdk_g