开发者

How to delete empty lines in multi-ranges in Vim

I get a text file:

<p>...</p>
<pre>
...

...
...
...
</pre>
<p>...</p>
<p>...</p>
<p>...</p>
<pre>

...
...

...
</pre>
<p>...</p>

Notice that: there are some empty lines between [pre]...[/pre].

I want to delete them.

But, I want keep those in [ p]...[/p]

The text file becomes:

<p>...</p>
<pre>
...
...
...
...
</pre>
<p>...</p>
<p>...</p>
<p>...</p>
<pre>    
...
...    
...
</pre>
<p>...</p>

I use the cmd below to located them:

/<pre>\n\zs\_.\{-}\ze\n<\/pre>

But I don't know what to do next!

I need a one-line-cmd to do this.

Any idea? Thanks!

The simpler, the better!


Edit: Thank you all. I just figure out how to do it with the help of my another question

:g/<pre>开发者_运维问答/,/<\/pre>/s/^$\n//


This one will clear out all empty lines within <pre> blocks:

:%s_<pre>\zs\_.\{-}\ze</pre>_\=substitute(submatch(0), '\n\n\@=', '', 'g')_g

WTF:

:%s_: starts a substitution command over all lines in the buffer. You can use any character after the s; using one that you're not using within the pattern (in this case _) means you don't have to escape it within the pattern.

<pre>\zs\_.\{-}\ze</pre>: minimal, multiline match of all characters within <pre> blocks.

_: delimits the match string from the replacement

\=: putting this at the beginning of the replacement indicates that the replacement is a vimscript expression to be evaluated.

substitute(submatch(0), '\n\n\@=', '', 'g'):

  • The replacement expression is a substitute(...) function call.
  • submatch(0): this gives the full outer match, in this case everything between \zs and \ze.
  • \n\n\@=: this RE matches any newline that's followed by a newline, without actually advancing past that second newline. The \@= element is known as a "zero-width lookahead assertion"; :help /\@ will give you more details.
  • the rest of it is pretty simple, just replace the newline with nothing for all occurrences. Note that the second newline (the one spotted by the lookahead) isn't considered part of the match and so doesn't get replaced (at least, not until the next iteration, when it will be replaced if it's followed by a third consecutive newline).

Finally, _g just closes the expression with a g flag to indicate that all instances should be replaced. I think the mnemonic is "global".


Your problem is very similar to the one exposed there.

Have a loop (with search, called with "no wrap") to search for first the opening tag, then the closing tag. This defines a range onto which you will apply the g/^\s*$/d_.

It may be easier to work backward as some lines will be deleted.

EDIT: the folowing one-liner seem to work as well

g/<pre>/,/<\/pre>/s/^\s*$\n//g


:%s/^$\n// will delete all empty lines from the file.

:%s/\(<pre>\)\(\n\|.\)*\(<\/pre>\)/\1\r\3/ will delete everything inside of <pre></pre> blocks.

This is not what you exactly want, but it could help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜