97

I'm a C# developer who has just recently decided to expand my knowledge of the tools available to me. The first tool I've decided to learn is Vi/Vim. Everything has been going well so far, but there are a couple of questions I can't seem to find the answer to:

  1. Lets say I wanted to yank a range of lines. I know there are many ways of doing so, but I would like to do it by line number. I figured it would be similar to how the substitute commands work, something like 81,91y. Is there a way to do this?

  2. I'm a little confused about the g command in normal mode. It seems to do a myriad of things and I can't really determine what the g command does at its core. I'm confused on whether or not it's a motion command or a kind of "catch all" for other commands ran through normal mode. Can someone please explain this or point me to a reference that gives a good explanation of the g command?

legoscia
  • 39,593
  • 22
  • 116
  • 167
jnadro52
  • 3,454
  • 3
  • 21
  • 17
  • 1
    Do you know about the command ":help" in vim(1)? – Steve Emmerson Jan 07 '10 at 19:29
  • Yes, but I was unable to find it in all the references. It turns out I was thinking I would do it from normal mode, but hometoast showed how it had to be done from command mode. For the g command, I just find that the help doesn't tie everything together as I would expect from the other commands. – jnadro52 Jan 07 '10 at 19:30
  • 3
    As an aside, I you might want to make one post per question. – Dana Jan 07 '10 at 19:34
  • 1
    I will do so in the future. I was more concerned with the first question, I just thought of the other one as I was typing the first. – jnadro52 Jan 07 '10 at 19:35

10 Answers10

158

Yank lines 81-91

:81,91y<enter>

If your fingers don't like to find the : and , keys, this would work as well (go to line 81, yank 11 lines)

81gg11yy 

My only use of g is 5gg. To go to the 5th line. 22gg: 22nd line. As jimbo said, it's really only a modifier for some other commands.

For completeness, (http://vim.wikia.com/wiki/Power_of_g) explains a lot of how g works in command mode.

Jens
  • 69,818
  • 15
  • 125
  • 179
hometoast
  • 11,522
  • 5
  • 41
  • 58
  • Wow, that was fast! I didn't try doing it from command mode, duh! Thank you very much for the quick response. – jnadro52 Jan 07 '10 at 19:28
  • 3
    Using capital letters provides variations, too: `gg` will go to the first line, while `G` will go to the last. Also, `5G` goes to line 5. Marks can be used in lieu of line numbers also (good for macros), ie: `:'a,52y` – NVRAM Jan 07 '10 at 19:50
  • 1
    If you're not afraid of the Shift key, `81G11Y` is even "shorter". – Jens Dec 05 '12 at 12:09
  • 1
    The downside of the normal mode method is you lose your "place"; you could conceivably `mx` before and `'x` after but then the command mode version becomes a lot more succinct. Humm... no sooner had I written this that I saw the answer from @Asta. – Eric Smith Jan 09 '18 at 12:05
  • I have the lines yanked but they don't seem to be copied, is there any additional step to go from yanking to copying? – William Ross Aug 03 '18 at 17:47
  • 1
    @WilliamRoss this actually puts the lines in a buffer for use in vim, not necessarily in your systems Clipboard where you could paste in to, say, Notepad with CTRL+V. See related question: [How to copy/paste text from vi to different applications](https://stackoverflow.com/a/10803813/2009) – hometoast Aug 06 '18 at 14:58
  • 1
    This amuses me because the whole reason I searched for the first solution was to avoid counting lines or doing a subtraction in my head. – Paul Parker Aug 10 '19 at 00:37
27

You can also copy the current lines to your present cursor location using 't'.

:81,91t.<enter>

This will paste the lines 81-91 under the line the cursor is on.

I learned this from http://vimcasts.org which is an excellent resource on VIM.

Asta
  • 1,569
  • 13
  • 23
15

I also like to use vim's relative line number option (set rnu) which means I can just enter:

:-10,-7ya a

to yank the text into named buffer a.

N.B. Specifying A will append what you're yanking to the current contents of buffer a.

Don't forget you can also copy blocks of text and move blocks of text around as well with the similar commands:

:-10,-7co .

means copy the four lines of text 10 lines above to below the current line, and

:-10,-7mo .

means move the four lines of text 10 lines above to below the current line.

Rob Wells
  • 36,220
  • 13
  • 81
  • 146
15

The G command goes to a certain line number, if it's accompanied by a count value. 81G puts you on line 81.

The y command can be combined with a movement, like G. So to yank everything until line 91 you can use y91G.

Together you get:

81Gy91G

Go to line 81, then yank while going to line 91.

sth
  • 222,467
  • 53
  • 283
  • 367
  • 2
    I'm wishing I could upvote this more than once. Something that helped me was to use this to yank to a register (in my case, register + i.e., the clipboard): ```81G"+y91G``` – mgarey Sep 05 '17 at 19:57
  • 1
    @mgarey is there no way to yank directly into a register using the line range syntax? `81,91y` and somehow target the register? – diplosaurus Apr 10 '18 at 19:08
  • 1
    @diplosaurus Probably, but I don't know. That sounds like a question you could ask on vi.stackexchange.com, if it's not already there or here on SO. I'd be interested. I'm no Vim expert. – mgarey Apr 10 '18 at 19:56
  • 3
    @mgarey Had to get creative with the google search but I found it here:https://stackoverflow.com/questions/16225366/vim-to-delete-a-range-of-lines-into-a-register. `:81,91y +` – diplosaurus Apr 11 '18 at 20:44
  • @diplosaurus `:81,91y +` does not work. It works for other registers like `:81,91y a` for example but does not seem to like the `+` register. Does this definitely work for other people? – ojunk Nov 03 '18 at 16:56
  • 1
    I've figured it out! `:81,91y a` works fine but if you want to yank to the `+` or `*` registers then you need to prefix it with `"` e.g. `:81,91y "+`. – ojunk Nov 03 '18 at 16:59
  • @ojunk definitely works for me (though i use `:y *`). Your quote may be commenting the register, so not working after all. Depends on how vim was build (with clipboard or not) – D. Ben Knoble Aug 11 '19 at 13:09
  • @diplosaurus Interestingly space character matters here. For e.g to copy the entire file to a register, used `:%y+` which gets yanked into "+. However the same command didn't work for register 'a' in this form: `:%ya` (gets yanked into default register, and not "a) , but works in this form: `:%y a` (yanked to "a) – Ambareesh Apr 27 '20 at 22:12
  • This is an excellent tip but uses the default register. Although not one shot, it's easy enough to copy after with `:let @a=@` and this may work with the clipboard also but I an on Linux. Also y ya yan yank are all the same command, perhaps why space is required for any a-z reg – chipfall Dec 30 '21 at 17:43
5

In addition to :91,96y a which yanks (y) lines 91 through 96 into register a, (pasted with "ap), the yanked lines can be appended to the register with:

:91,96y A

I.e. the capitalization of the A register causes an appending operation into register a instead of an overwrite. Capitalization of the register always works like this, e.g. :let @A=';' appends a ; to register a.

Using plus (+) or minus (-) references lines relative to the current cursor position:

:-10,+10y b

I.e. it would yank(y) 21 lines around the current cursor position and put them in register b.

An absence of input actually represents the current cursor position as well, which means that this:

:-5,y a

would yank the text from 5 lines above to current cursor position into named buffer a, and:

:,+5y a

would yank the 5 lines after the current cursor position into buffer a.

Note: If you have a macro in buffer a it was just overwritten by the previous yank, as yank registers and macro registers are really the same thing. Which is why, coincidentally, you can paste a macro, edit it, and then yank it back into it's register. I personally use letters reached by my left hand for yanks, and letters reached by my right hand for macros.

Moving blocks of text around, looks like this:

:+10,+13m.

which means move the four lines positioned 10 lines ahead of current cursor, to below the current line.

Addendum

I previously confused ya in :91,95ya a to be somehow synonymous with ya{motion} where the motion was supplied by 91,95. This was incorrect and the "a" in ya is completely unnecessary. In my defense, my help yank does not convey that ya is a possible alias of yank.

Paul Parker
  • 1,163
  • 12
  • 23
  • 1
    `:ya` is an abbreviation of `:yank`, so I’m not sure how I feel about *yanks all lines*. But good job condensing some of the scattered information – D. Ben Knoble Aug 11 '19 at 13:12
  • I thought so too, until I looked at `:help yank`. There is no alias `ya` for `yank`. You're right though, the `a` doesn't stand for "all", it technically stands for "a". I prefer to say "all" still though, since it makes more sense to me. – Paul Parker Aug 12 '19 at 00:42
  • 2
    `:[range]y[ank] [x] Yank [range] lines [into register x]` the square brackets in `y[ank]` indicate that the `[ank]` are optional. `:y`, `:ya`, and `:yan` are implicitly aliases for `:yank` – D. Ben Knoble Aug 12 '19 at 00:43
  • I stand corrected :) The a is not necessary. Will edit the answer to reflect. – Paul Parker Aug 12 '19 at 00:50
  • 1
    Your addendum is nice, but I was referring to your very first line, where you use the ex command `:ya` and not the normal command `y` – D. Ben Knoble Aug 12 '19 at 00:54
  • Oh, `ya` is a holdover from `ex`. From the `ex` manual: `( . , . )yank buffer count abbr: ya` – Paul Parker Aug 12 '19 at 01:04
4

g doesn't do anything by itself. It's one of a couple meta-commands that holds a bunch of sorta-unrelated commands.

z is yet another command like that.

Tshilidzi Mudau
  • 7,373
  • 6
  • 36
  • 49
Jimbo
  • 320
  • 3
  • 14
  • Thank you. I understand now that it's just used for different purposes. When I try to learn these tools, I try to associate the commands with something I can abstract so that I remember how to properly use it. It seems like the g command is just one of those things that you need to memorize to use properly. – jnadro52 Jan 07 '10 at 19:34
3

The best solution would be to enter "visual mode", by pressing v. And after selecting lines just copy them by pressing y. Then paste copied lines by pressing p.

Taras Vaskiv
  • 2,215
  • 1
  • 18
  • 17
2

Vim's :help index describes g as:

|g|             g{char}            extended commands, see |g| below

Scroll down (or :help g) for a list.

Matthew Slattery
  • 45,290
  • 8
  • 103
  • 119
  • 1
    I was familiar with the :help but I was NOT familiar with :help (command). That will be very useful in the future. Thank you kindly, sir. – jnadro52 Jan 07 '10 at 19:39
2

As a long time Vi/Vim user I tend to use 'marks' instead of line numbers (or 'line markers'). It works like this: m is the 'mark' character; then use any letter to identify/name the mark. To return to a mark preface the named mark with a single quote ( 'a)These marks can be used as the range. Examples:

File:
    <line 1>
    <line 2>
    <line 3>
    <line 4>
    <line 5>

When in command mode move cursor to line 2, typema. scroll to line 4, typemb. To yank from mark a to mark b type:

    :'a,'byank

To delete from mark a to mark b type:

    :'a,'bdel

To search from mark a to mark b and replace 'ine' with 'ink':

    :'a,'bs/ine/ink/g

To copy mark a through mark b and paste below the current position (the 'dot' always references the line where the cursor currently is positioned):

    :'a,'bco . 

Shift lines of code, between mark a through mark b, one tab to the right (use opposite chevron, <, to move left):

    :'a,'b> 

In command mode you can move back to marks by simply typing 'a to move back to the line marked a. Typing '' moves you back to previous position (unfortuantely only remembers the previous position, not two back).

You can yank to named buffers, copy, delete lines, search&replace just portions of your code, etc. without needing to know the line numbers.

BentChainRing
  • 382
  • 5
  • 14
  • https://vim.fandom.com/wiki/Cut_or_copy_lines_without_counting_the_lines provides an even more succinct use of markers. – Thomas Hedden Nov 07 '21 at 01:30
1

To yank lines from line number 81 to 91 :

approach 1: 81gg11yy

not bad but you have to do little bit of math to find out how many lines to yank

approach 2: 81gg then shift+v then 91gg then y

BEST IN MY OPINION because this is straight forward, you only have to know the obvious thing i.e from which line number to which line number you want to yank

Firoj Siddiki
  • 1,649
  • 1
  • 20
  • 22