2

I have a file containing special comments in the following forms:

// SPECIAL
// Some stuff
// Some other stuff
// Last line of other stuff

So I need to be able to delete the line containing SPECIAL and the 3 nexts. Assuming the SPECIAL does not appear in the 3 lines after one SPECIAL.

I know I can search for SPECIAL and then 4dd but there are a lot in the file so I would prefer to do it automatically.

How to do this?

  • Are they all in the same file? – still_dreaming_1 Jun 29 '16 at 14:45
  • 2
    "I have a file containing..." – Tumbler41 Jun 29 '16 at 14:46
  • One thing not clear to me. If the number of lines between two SPECIAL lines was less than 3, what do you want to do? – Kent Jun 29 '16 at 14:55
  • Nice question, but not in my case, let me clarify that. – nobe4 Jun 29 '16 at 14:56
6

You could use the following command:

:g/SPECIAL/.,.+3d

Which can be detailled like this:

:g/      Apply a command on all the lines matching a pattern
SPECIAL/ The pattern to match
.,.+3d   The command to execute
.,.+3    Is a range. "." represent the current line (i.e. the matched one
         It is updated each time a line is matched
         The full range says "apply the command on the current line and the 3 following"
     d   Is the delete function 

See :h :d


EDIT As usual, @romainl had a cool trick to improve the answer, thanks to him:

:g/SPECIAL/,+3d

Vimgolfers will like it!

  • 1
    This command works for OP's example, but it has problem if there were lines (num<3) between two SPECI.. lines – Kent Jun 29 '16 at 14:47
  • As far as I read the question, it seems that the pattern and the next three lines have to be deleted. I hope that user knows what the file has exactly. – SibiCoder Jun 29 '16 at 14:53
  • 1
    Yes, I do know the content of my file. – nobe4 Jun 29 '16 at 14:55
  • 2
    …and shortened to :g/SPECIAL/,+3d. – romainl Jun 29 '16 at 15:08
  • 1
    Vimgolf: :g/SPECIAL/d4 – Peter Rincker Jun 30 '16 at 18:01
2

You can use vim macros!

Edit: As @statox suggested, we can search the pattern first and then record macro. It will avoid searching the same pattern every time.

Search for the pattern /pattern.

Press qaq to clean the register a. Press qa to start recording. Press n to search the next occurrence of the pattern. Then press 4dd to delete four lines including that line. Press @a to repeat the process. Press q to stop recording.

Now onwards, you can press @a once. It will search for the pattern and delete four lines. :)

Explanation:

           qaq - start recording in `a` register and stop recording. (Indirectly, means that you are clearing register a.
  • 2
    Actually you would need to first search for the pattern /SPECIAL then use n in the macro qan4ddq – statox Jun 29 '16 at 14:54
  • 1
    @statox put /pattern<cr> in macro is also ok. – Kent Jun 29 '16 at 14:56
  • 1
    or use a global command that you apply a macro on? – nobe4 Jun 29 '16 at 15:01
  • 1
    @Kent You are right, it is just a matter of preference so I should have phrased my comment differently :-) The nested macro if a good idea here. – statox Jun 29 '16 at 15:02
  • 2
    @statox perhaps I played vimgolf too much. /pat<cr> will beat /pat<cr> then n ;-) – Kent Jun 29 '16 at 15:04
2

Even though you say you want a single command that does it automatically, I would suggest not doing that unless you really have a ton of them. Often attempting to come up with one command that does it all in one go is problematic compared to a simpler approach. You might have to try several commands before you come up with one that really works, whereas with a simpler approach you will probably get it right on your first or second attempt and you can think of what to do much quicker and without asking for help. Also, I often find that while I believe I know exactly how this pattern I want to delete appears every time in the file, there are often slight variances of it I had forgotten about or was not aware of. These variances might get picked up by the single command approach and deleted. You may not have wanted to delete them or it might delete more or less than what you wanted for a particular variance.

It is safer to let yourself see each match and decide to or not to delete it. Here is the approach I would take.

Type the following: /\/\/ SPECIAL

At this point it should be clear that you did or did not enter the search correctly before you ever delete anything, which is one of the advantages of this approach.

Once you verify you searched for the right thing, instead of pressing 4dd, enter linewise visual mode with a captial V. Instead of finding how many lines to go down, which will consume some of your mental visual processing ability for the day, do it the lazy way. Just press j a few times until it looks right. That way is much easier to visually process. This also has the advantage of preventing you from mistakenly thinking you needed to delete 4 lines when you actually needed to delete 5 or some other amount, as you can clearly see highlighted what you are about to delete.

Once you have highlighted the lines you want to delete, just press d to delete them. You only need to press it once, since you are in linewise visual mode. At this point, you can see that you either did or did not actually want to delete it that way without altering the entire file. It is not uncommon to notice that while you did delete what you intended, it would be better to also delete the line below it, as it is just white space. This is one of the advantages of this approach, you can refine exactly what you want to delete in one place before moving on to the rest of the file. The key here is to make sure that you undo the change that wasn't quite correct, and then delete all of it with a single command so that . will work well for you going forward.

Once you have deleted what you want, press n to jump to the next search result. Look and see if you really want to delete that next one. To delete it, just press . to repeat your last deletion. Keep doing this until they are all deleted. So basically, you are pressing n. over and over again.

This way with each result you can visually decide if that match is really the same and if you really want to delete it each time, and then deleting it is as simple as pressing .. If you encounter a match where you want to delete it differently, ignore it for now, move onto the next result. Otherwise, you will mess up your .. Finish deleting all the places that don't require any changes in how you delete it. Then keep pressing n and try some variance of this approach to delete the remaining matches.

  • Thanks for taking the time of writing this. I am aware of the possible destruction implied by the global command. But this case is specifically fitted for the "match and delete" workflow. In some more nebulous cases, a one-by-one approach may be better, but I am sure of the content of my file and don't mind taking the shotgun to this. – nobe4 Jun 29 '16 at 15:26
  • 1
    @nobe4 Sounds good. At least I have the thought process described here so you and other people can see if this answer applies to them or not. Hopefully it will open up someones mind see a new approach that will help them at some point. – still_dreaming_1 Jun 29 '16 at 15:31
  • @stilldreaming. I hope you can answer in a simple way :) – SibiCoder Jun 29 '16 at 17:07
  • 1
    @SibiCoder For some people more words is simpler ;) I am describing things here in enough detail that someone who is not already familiar with all those concepts can kind of get the idea just from reading this. – still_dreaming_1 Jun 29 '16 at 21:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.