iGio90
iGio90

Reputation: 298

sed: insert a line in a certain position

i was just looking around but i didn't find anything that works for me. I would like to insert a new line (basically an html table row) on top of the other rows.

<table id="tfhover" class="tftable" border="1">
<tr><th>HEADER1</th><th>HEADER2</th><th>HEADER3</th><th>HEADER4</th></tr>
<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2</td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td></tr>
</table>

So, is there anyone that can suggest me a sed cmd that will insert a new:

<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2</td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td>

just below the HEADERS?

Thanks!

Upvotes: 0

Views: 8922

Answers (2)

jubilatious1
jubilatious1

Reputation: 2341

Using Perl

~$ perl -pe 'BEGIN {$str = q(<table id="tfhover" class="tftable" border="1">)};  \
             s{\Q$str\E}{$&\n<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2<td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td>};'  file

#OR

~$ perl -pe 'BEGIN {$str = q(<table id="tfhover" class="tftable" border="1">)};  \
             s{(\Q$str\E)}{$1\n<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2<td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td>};'  file

Using Raku (formerly known as Perl_6)

~$ raku -pe 'BEGIN my $str = Q[<table id="tfhover" class="tftable" border="1">];  \
             s{$str} = "$/\n<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2<td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td>";'  file

#OR

~$ raku -pe 'BEGIN my $str = Q[<table id="tfhover" class="tftable" border="1">];  \
             s{($str)} = "$0\n<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2<td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td>";'  file

Above are answers coded in Perl and Raku. In both languages $str is assigned a single-quoted (i.e. non-interpolated) target line to insert after--the OP's first line of text. So to clarify (similar to the answer by @clt60), HTML isn't being "parsed" here--instead a single line of HTML is matched with a literal string, and a \n newline and new text is inserted afterwards (e.g. \nnewtextinserted).

The -pe command-line flags in both Perl and Raku invoke sed-like behavior, and answers in both languages use a match or capture variable in the replacement half of the s/// operator (followed by the aforementioned \nnewtextinserted).

  • Here in Perl to save on backslashing custom delimiters are used, i.e. s{…}{…}. Same in Raku, but also the use of custom delimiters has changed somewhat: in addition to things like s!foo!bar! you can use the s{…} = "…" format. To explain from the Raku docs: "Paired characters, like curly braces, are used only on the match portion, with the substitution given by assignment (of anything: a string, a routine call, etc.)."

  • In Perl the LHS (recognition domain) of the s/// operator is effectively a double-quoted string. So to disable regex interpolation the \Q…\E form must be used in Perl. By comparison, note that 1). Raku escapes characters in single-quoted strings by default, 2). Raku requires the my keyword, and 3). in Raku quoting constructs square brackets are preferable.

  • In Raku, Q is the plainest-of-the-plain quoting construct: even backslashes that would otherwise truncate the string are not honored (use q if you want internal backslashes escaped). Quoting constructs are quite varied/plentiful in Raku: see the final URL at bottom.


Sample Input:

<table id="tfhover" class="tftable" border="1">
<tr><th>HEADER1</th><th>HEADER2</th><th>HEADER3</th><th>HEADER4</th></tr>
<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2</td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td></tr>
</table>

Sample Output (all four code examples):

<table id="tfhover" class="tftable" border="1">
<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2</td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td>
<tr><th>HEADER1</th><th>HEADER2</th><th>HEADER3</th><th>HEADER4</th></tr>
<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2</td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td></tr>
</table>

https://perldoc.perl.org/perlre
https://perldoc.perl.org/functions/quotemeta

https://docs.raku.org/language/regexes
https://docs.raku.org/language/quoting

Upvotes: 0

clt60
clt60

Reputation: 63974

So for the start, we have a file with the following lines, called datafile.txt

1 some test lines here
but not all lines contain nubers
3 and here is the last one

and we have one bash variable $ADDED with the line content what want add

ADDED="==This is the new line=="

So, add line after the first line

ADDED="==This is the new line=="
< datafile.txt sed "1a \\
$ADDED
"

the result:

1 some test lines here
==This is the new line==
but not all lines contain nubers
3 and here is the last line

Add line after all lines what are starts with a number

< datafile.txt sed "/^[0-9]/a \\
$ADDED
"

the result:

1 some test lines here
==This is the new line==
but not all lines contain nubers
3 and here is the last line
==This is the new line==

Add line to the start, so insert before first line

< datafile.txt sed "1i \\
$ADDED
"

result

==This is the new line==
1 some test lines here
but not all lines contain nubers
3 and here is the last line

You can "substitute" the end of the line for adding a new one

< datafile.txt sed "/all/s/$/\\
$ADDED/"

the above example add line after the line what contains word "all" by substitution

1 some test lines here
but not all lines contain nubers
==This is the new line==
3 and here is the last line

You can even split line and add between

< datafile.txt sed "/all/s/\(.*lines \)\(.*\)/\1\\
$ADDED\\
\2/"

the above will search for the line what contains the word "all" and split it after the word "lines". The result:

1 some test lines here
but not all lines 
==This is the new line==
contain nubers
3 and here is the last line

Last thing. It is impossible to parsing HTML with regural expressions, check the link in sputnik's comment.

BUT, that's not mean than it is impossible match some parts of HTML files. If you know what you want match (and not parse) - you can safely use regular expression for HTML too. Simply, many peoples here don't know the difference between parsing and matching.

So, if your html files has well known structure, e.g. you are sure than your html will the above structure all times, you can safely write:

<your_file.html sed "/^<tr><th>/a \\
<tr><td>new Row:1 Cell:1</td><td>Row:1 Cell:2</td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td>
"

and you will get

<table id="tfhover" class="tftable" border="1">
<tr><th>HEADER1</th><th>HEADER2</th><th>HEADER3</th><th>HEADER4</th></tr>
<tr><td>new Row:1 Cell:1</td><td>Row:1 Cell:2</td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td>
<tr><td>Row:1 Cell:1</td><td>Row:1 Cell:2</td><td>Row:1 Cell:3</td><td>Row:1 Cell:4</td></tr>
</table>

simply because we NOT PARSING the html code, we are only MATCHING some line patterns..

Upvotes: 9

Related Questions