0

Suppose I have the following input as shown below. What I would like to do is to visually select lines 2 through 4 (shift + v) and then delete the word dog.

How can I do that? I know I can use something like :s/dog// on my selection, but I was wondering if there's a more straightforward way.

1 The quick brown dog
2 dog jumps
3 over the
4 lazy dog,
5 but it should be just a fox.

The final output should be (affected only by the visual selection on lines 2 through 4):

1 The quick brown dog
2  jumps
3 over the
4 lazy ,
5 but it should be just a fox.
Cyrus
  • 84,225
  • 14
  • 89
  • 153
Rod Elias
  • 706
  • 6
  • 14
  • 1
    https://vi.stackexchange.com/ – Rob Jun 16 '22 at 22:45
  • What could be "more straightforward" than `:s/dog//`? It does exactly what you want with very clear semantics. Or do you mean "quicker"? – romainl Jun 17 '22 at 05:38
  • No, `s/dog//` doesn't do the job. It will be removing "dog" in the first line, too. – robni Jun 17 '22 at 09:01
  • @robni re-read the question again but slowly. OP is in visual mode so `:s/dog//` effectively becomes `:'<,'>s/dog//`, which constrains the substitution to the visually selected lines, which is equivalent in this case to `:2,4s/dog//`, which does exactly what OP wants. – romainl Jun 17 '22 at 13:16

4 Answers4

1

When you are in visual mode, pressing : automatically inserts the visual range in the command-line so whatever Ex command you use after that is going to work on the visually selected lines:

  1. : becomes :'<,'>, in which '<,'> is a range beginning on the first line of the visual selection and ending on the last line of the visual selection.
  2. After that, you can do s/dog<CR> (no need for the //) to substitute the first dog with nothing on every selected line. This is effectively equivalent to doing :2,4s/dog<CR>.

From a semantic point of view, :s/dog<CR> is as close as you can get with the built-in features to "remove dog in the current visual selection" so, barring making an hypothetical custom mapping that would only save a couple of keystrokes, you are unlikely to find a more "straightforward" way.

romainl
  • 186,200
  • 21
  • 280
  • 313
0

I think there is no way in way to just replace a specific word in specific lines with visual selection. You can also use sed for that (look at #5).

Anyways: Here are 4 way to delete the word dog in a file and one way to do it with sed:

1 (with visual mode):

  1. Type v to enter visual character mode
  2. Highlight dog
  3. Press d for deleting

2 (with substitute and confirmation):

:%s/dog//gc

g stands for global

c stand for confirmation

You will be ask for every entry, what to do with.

3 (with substitute):

:2,4s/dog//

4 (with search mode):

/dog

Type: n for next match

Type: d for deleting the match

For further information: Search and Replace

5 (with sed):

sed 2,4\s/dog// filename
robni
  • 904
  • 2
  • 6
  • 20
  • I'm wondering if there's a way to use visual selection and then delete the word that I want without the need to use "find and replace". – Rod Elias Jun 16 '22 at 23:02
0

That's impossible.

Why?


tl;dr

I think, you are envisioning something like a normal mode within visual mode (so that you can "move and delete like in Vim" while you are in visual mode). Such a thing doesn't exist.


Think about it: if you visual select some lines, then those lines, and nothing else, are the object of whatever action you do next (d, s, c, or whatever).

But you want to take an action not on those visually selected lines, but on words within them. But how can you tell Vim to take action on the words dog and not on other words? You can do that with movements, but as long as you are in visual mode, that's not possible, because any movement will just change the visual selection, and not allow you to somehow move within it.

This means that you need to abandon the visual selection so that you can move to those words and use them as the textual object for the action.

If you really want to start from the visual selection, then the only way to give the info that you want to take action on the words dog, is to type them out while you are in visual mode. And that's precisely what the :s approach does.

Enlico
  • 23,259
  • 6
  • 48
  • 102
0

You can take advantage of the marks '< and '>: they store the start/end position of the visual selection and they keep their value after you exit the visual mode.

In command line mode, Ctrl-RCtrl-W inserts the word under the cursor.

By combining this, you can create a mapping like that:

noremap <c-d> :'<,'>s/<c-r><c-w>//<cr>

Then to use it:

  • first select the wanted zone with V;
  • hit Esc to exit visual mode;
  • move your cursor under the word you want to delete;
  • then trigger the mapping, in this example Ctrl-D.
yolenoyer
  • 8,797
  • 2
  • 27
  • 61