TransWikia.com

How do you change the last n characters for a range of lines?

Vi and Vim Asked on August 31, 2021

Generally you can select a visual block for the first n characters of a range of lines, and just press c, insert characters, and press Esc to have it apply to all.

However, this method is rarely possible for all the latter characters, because lines of code are likely to vary in length.

How can I easily change the last three characters of a range of lines?

4 Answers

It would not work all the time, but maybe you could temporarily right-align the right border of the code.

Suppose you have the following code containing 3 lines, each with the same level of indentation (8):

        here is foo
        here will be foo
        here was foo

And you want to change foo with bar. You could use the following commands:

  • vip = select the current paragraph
  • :right = right-align it
  • ff = move the cursor on the f character
  • C-v G = go into visual block mode and select the column of f characters
  • C = cut everything after the column
  • bar Esc = insert bar and escape to go back in normal mode
  • gv = visually select the last changed text (the bar column)
  • :left 8 = left-align the paragraph, giving it back its original level of indentation 8

It would look like this: enter image description here

If however, the lines in the block have different levels of indentation, then I don't think this solution can work, as you would probably have to remember the original level of each line, then fix it afterwards.

Correct answer by user9433424 on August 31, 2021

I would approach it with a macro + visual selection.

  1. start recording a macro
  2. do the changes
  3. stop the macro recording
  4. Visual select all lines that needs this change
  5. apply the macro

That would look the following:

qq$Cfoo<ESC>q

record the macro (qq) with the change ($Cfoo) end the macro (q)

Visual select with V followed by the move keys to select the lines of interest. Then apply the macro for selection:

:normal @q

Note: caused by the visual selection, after pressing : you see the following :'<,'> there you just append normal @q. So that the whole command reads like:

:'<,'>normal @q

Now all lines have been changed. This pattern works for so manny repetitive tasks, not only EOL editing.

Answered by sassman on August 31, 2021

Building on @statox's answer,

:'<,'>s/v.{3}$/foo/
  • v very magic option, see :h v for more info
  • .{3}$ last 3 characters of line
  • foo desired replacement string

Answered by Sundeep on August 31, 2021

EDIT Here is a better solution than the one I gave previously:

'<,'>g/.*/norm! $4hCfoo
  • '<,'> apply the command to the visual selection
  • g/.*/ apply the global command on all the lines (of the visual selection)
  • norm! interpret the following string as a normal command
  • $4hCfoo go 4 characters before the end of the line and replace them by foo

EDIT 2 And another one for the fun:

'<,'>g/.*/execute "s/\%" . (len(getline('.'))-4) . "c.*$/toto"

I think it is overcomplicated but is interesting to understand the behavior of the global command:

  • '<,'> Apply on the visual selection
  • g/.*/ Apply the global command on all the lines of the visual selection
  • execute "..." Execute the following string as a command (We use it to insert a calculation)
  • s/ Aplly a substitution on the following pattern
  • \%" Beginning of the pattern of the form %Xc.*$ i.e. from the Xth column to the end of the line
  • . (len(getline('.'))-4) . Calculate the number of the column based on the size of the line minus the number of column to change
  • "c.*$ end of the pattern
  • "toto" The string to use as replacement

The interesting part is that to be able to use . (len(getline('.'))-4) . in the substitution you have to use the global command:

The global command will execute the command on each selected lines one after one, so getline('.') is updated on each line. If you only used

execute "'<,'>s/\%" . (len(getline('.'))-4) . "c.*$/toto"

The getline('.') would only be the current line and thus you would get unexpected results.


There are probably some better solutions but you could do it using a macro. For example to replace the last 4 characters by foo:

qa$4hCfoo<Esc>jq
  • qa record a macro
  • $4h go 4 character before the end of the line
  • C remove the end of the line and enter insert mode
  • foo the text to insert
  • <Esc> leave insert mode
  • j go to the next line
  • q stop recording the macro

You can then go to the first line and use 5@a to apply the macro on the 5 next lines.

Answered by statox on August 31, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP