4

I have blocks of the following form:

    String that is not supposed to be enclosed in quotes
    String that is supposed to be enclosed in quotes

    String that is not supposed to be enclosed in quotes
    String that is supposed to be enclosed in quotes

    String that is not supposed to be enclosed in quotes
    String that is supposed to be enclosed in quotes

    String that is not supposed to be enclosed in quotes
    String that is supposed to be enclosed in quotes

I need to put the lines that state that they are supposed to be enclosed in quotes in quotes:

    String that is not supposed to be enclosed in quotes
    "String that is supposed to be enclosed in quotes"

    String that is not supposed to be enclosed in quotes
    "String that is supposed to be enclosed in quotes"

    String that is not supposed to be enclosed in quotes
    "String that is supposed to be enclosed in quotes"

    String that is not supposed to be enclosed in quotes
    "String that is supposed to be enclosed in quotes"

Is there a semi-automatic way of doing this with Vim? I thought that a possible solution might involve the g command.

4 Answers 4

8

Using regular expressions:

:%s/.*is supposed.*/"&"/

If by "semi-automatic" you mean you would like to be prompted before each substitution, just add the /c modifier to the substitution pattern:

:%s/.*is supposed.*/"&"/c

Explanation

  • :%s means apply this substitution to all lines in the current buffer
  • The pattern we match is any line containing the words is supposed (if some other lines contain the words "is supposed" without "to be enclosed in quotes" following them, you can always change the pattern to .*is supposed to be enclosed in quotes.*
  • The string we use to replace the matched pattern is "&", where & stands for whatever was matched by the pattern.
7
  • +1 I normally use \0, I learned about & now :)
    – Bernhard
    Jun 23, 2014 at 10:40
  • @Bernhard ...and I just learned of \0 :)
    – Joseph R.
    Jun 23, 2014 at 10:41
  • then you might be thrilled to learn about \1 to \9 :)
    – Bernhard
    Jun 23, 2014 at 10:43
  • @Bernhard :D These I knew about...
    – Joseph R.
    Jun 23, 2014 at 10:45
  • 2
    Also :g/is supposed/s/.*/"&"/ Jun 23, 2014 at 11:04
2

The famous surround plugin provides various mappings that make this quick and easy. To quote an entire line (without indent), just use yss". You can apply this to all matching lines of your example text automatically via the :global command and :normal:

:g/is supposed/normal yss"

Or just do a search for matching lines and repeat via n and .

2

I almost always prefer macros to search n substitute because they are more powerful and less to memorize while still retaining the option to interactively check before you leap. Try this on the first line you would like to change (do not type the spaces I put around ESC and ENTER for readability):

qqI" ESC $bea" ESC /is supposed ENTER zzq

What it does:

  • qq starts a macro named "q" (qa would start macro "a")
  • I" ESC Inserts a " before the first word, not at the beginning of the line like "0" would do, thus preserving the usually valuable white space there.
  • $bea" ESC Goes to the end of the line ($), but then backs up a word (b) and forward again to end of it (e), finally appending (a) the ". This maneuver appends after the last word of the line even if followed by usually useless trailing whitespace.
  • /is supposedHaving performed the edit this searches for the next instance of "is supposed", which could be many pages further down, and nicely positions the cursor there for you to look at and decide whether continuing the edits. If no "is supposed" is found the macro quits with no damage.
  • zzq nicely centers the line on the page (zz) so you can see a few lines beyond the current one. Useful when you fast apply the macro and want to glance a couple moves ahead. "q" ends the definition of the macro, which also happens to be called "q".

How to use:

  • The first line was already changed when done defining the macro above.
  • If there is an error you can simply undo this one line and try again.
  • The cursor is now positioned on the second match, if any, and nicely centered in the page.
  • You may apply the macro if you want (or other, similar macros!), with @q, which would edit the line and position you on the third match.
  • You may reapply the last macro with @@ (faster than @q).
  • You may do several at once, like: 111@@. Remember that if there is ANY error while applying the macro there are no further repetitions.
  • Or you may manually skip ahead with PageDown and friends and reapply the macro.
  • And you can interleave the macros with any other edits whatsoever.
  • And you can :tab next to apply this macro to other buffers or files.
  • Cherry on pie: the macro is remembered even after you exit vim!

Once you get comfortable with macros you'll have amazing powers!

2
  • nice answer with macros! The only problem is that if I go to a line that doesn't contain the "is supposed" and start applying the macro there, that first line will be quoted anyway.
    – Santiago
    Jun 5, 2017 at 11:08
  • @Santi In your case do a "/is supposed" once before applying the macro. Or rewrite the macro so you do the search first. In the general case I don't recommend that, because I want to see the effects of the macro at least once before committing to using it thoughout the file.
    – Mayavimmer
    Jun 19, 2017 at 5:27
0

The regular expression version works if your lines really are like that, and there's some distinguished string that identifies which lines are which. Otherwise, we can record a macro to do what you want.

To do that, go to the start of line 2 and press:

qq I" Escape A" Escape 3j q

That will quote the first line and take us to the next one to look at. Then you can press @q to replay all the actions you just took, or, say, 5@q to do it five times.

How that works: q is the command to start recording a macro, which we're also calling q (you can pick any letter). In that macro, we insert a double quote at the start of the line (I"), leave insert mode (Escape), append a double quote at the end of the line (A") and leave insert mode again. We go down three lines (3j) to the next line to be quoted. q stops recording the macro.

After that, we're back somewhere just like where we started, so we can run the macro (@) we saved as q to do it again to the next pair of lines. With a count before the @, like in 5@q, we do it that many times.


Rather than 3j, if the spacing is somehow irregular, you can use }}k: go down two paragraphs to the blank line after the next one (}}) and back up (k). Either way, running the macro is the same.

In fact, you can record any series of actions that does what you want and gets you back to where you wanted to be. So long as the steps you take make sense in every context you're going to run it on, you can start a macro, make all the changes you need and move to the next location, then stop the macro and repeat.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .