woollybrain
woollybrain

Reputation: 853

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 - e.g., 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?

Upvotes: 7

Views: 5786

Answers (6)

Vijay
Vijay

Reputation: 67309

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

Upvotes: 1

Dave Cross
Dave Cross

Reputation: 69314

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?

Upvotes: 3

Zaid
Zaid

Reputation: 37156

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;

Upvotes: 3

romainl
romainl

Reputation: 196886

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, &.

Upvotes: 9

Kent
Kent

Reputation: 195269

vim way:

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

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

enter image description here

Upvotes: 16

Chris Seymour
Chris Seymour

Reputation: 85883

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

Upvotes: 9

Related Questions