简体   繁体   中英

How do I insert a line above specific lines in a file using Vim or Perl?

I'd like to insert the line

<hr />

above every occurrence of a header 2 line in a file - eg, above this pattern

<h2>variable pattern here</h2>

So the above should become

<hr />
<h2>variable pattern here</h2>

How can I do this with Vim, Sed or Perl?

vim way:

cmd :g/<h2>/normal O<hr /> will do the job.

see it here: (I took the example from sudo_O)

在此输入图像描述

With sed you could do sed '/<h2>/i <hr />' :

$ cat file
<html>
<h2>variable pattern here</h2>
<h3>not here</h3>
<h2>heading</h2>
<h2>Something</h2>

$ sed '/<h2>/i <hr />' file
<html>
<hr />
<h2>variable pattern here</h2>
<h3>not here</h3>
<hr />
<h2>heading</h2>
<hr />
<h2>Something</h2>

The first part /<h2>/ matches line containing <h2> and the second part uses the i command to insert <hr /> above the matched line.

A nice option with sed is -i this save the changes back to the file instead of printing to stdout but be sure that the changes are correct first.

sed -i '/<h2>/i <hr />' file

One of the many ways to do that in Vim:

:g/h2/norm O<hr /><CR>

Breakdown:

  1. :g[lobal] acts on every line that match a pattern, see :h :global .

  2. h2 the pattern we are looking for, it could be made a bit smarter, probably.

  3. norm[al] runs a normal mode command, see :h :normal .

  4. O opens a new line above the current line and enters insert mode.

  5. <hr /> is what you want to insert.

  6. We hit <CR> ( <RETURN> ) to run the whole thing.

Another way, using a single substitution:

:%s/^\s*<h2/<hr \/>\r&<CR>

Breakdown:

  1. :%s[ubstitute]/ performs the substitution on every line of the buffer, see :h :s .

  2. ^ anchors the pattern to the beginning of the line.

  3. \\s* matches any number (0 to many) of white space characters. It is not strictly needed if you are sure that all your HTML tags are on column 1.

  4. <h2 is the pattern we are really looking for.

  5. <hr /> is what we want to insert.

  6. Since we want it to be on its own line, it is followed by a \\r ,

  7. and, finally, the matched text, & .

use strict;
use warnings;
use Tie::File;

tie my @file, 'example.html'
  or die "Unable to tie file: $!";

@file = map { m!<h2>.*</h2>!
            ? ( "<hr />", $_ )
            : $_ } @file;

untie @file;

Command line solution in Perl.

perl -i~ -p -e'/<h2>/ and $_ = "<hr />\n$_"' your_file.html

Explanation of command line flags:

  • -i In-place editing (replace existing file), back-up to your_file.html~
  • -p Print each line in the file
  • -e Code to execute for each line in the file

If the line contains ( /<h2>/ ) then prepend <hr /> to it (the current line is in $_).

But have you considered if this is the best approach? If you want to add a line above every H2 element, then perhaps you should do that with CSS?

perl -plne 'print "<hr />" if(/\<h2\>variable pattern here\<\/h2\>/)' your_file

Input file:

> cat temp
<h2>variable pattern here</h2>
1
<h2>variable pattern here</h2>
2
<h2>variable pattern here</h2>
3
4
<h2>variable pattern here</h2>

Now the execution

> perl -plne 'print "<hr />" if(/\<h2\>variable pattern here\<\/h2\>/)' temp
<hr />
<h2>variable pattern here</h2>
1
<hr />
<h2>variable pattern here</h2>
2
<hr />
<h2>variable pattern here</h2>
3
4
<hr />
<h2>variable pattern here</h2>

This will just output to the console. If you want to change it inplace:

perl -pi -lne 'print "<hr />" if(/\<h2\>variable pattern here\<\/h2\>/)' your_file

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM