sed:在某个位置插入一行

问题描述 投票:0回答:2
linux bash sed
2个回答
9
投票

首先,我们有一个包含以下几行的文件,名为

datafile.txt

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

我们有一个 bash 变量

$ADDED
,其中包含要添加的行内容

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

因此,在第一行之后添加行

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

结果:

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

在所有以数字开头的行之后添加行

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

结果:

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==

将行添加到开头,因此在第一行之前插入

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

结果

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

您可以“替换”行尾以添加新行

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

上面的示例通过替换在包含单词“all”的行后面添加行

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

您甚至可以分割线并在之间添加

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

上面将搜索包含单词“all”的行,并将其拆分在单词“lines”之后。结果:

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

最后一件事。使用正则表达式无法解析 HTML,请检查 sputnik 评论中的链接。

但是,这并不意味着不可能匹配 HTML 文件的某些部分。如果你知道你想要什么 match (而不是解析) - 你也可以安全地使用 HTML 的正则表达式。简单来说,这里很多人不知道解析和匹配之间的区别。

因此,如果您的 html 文件具有众所周知的结构,例如你确信你的html将一直是上述结构,你可以放心地写:

<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>
"

你会得到

<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>

仅仅因为我们不解析 html 代码,我们只是匹配一些线条图案..


0
投票

使用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

使用 Raku(以前称为 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

以上是用 Perl 和 Raku 编码的答案。在两种语言中,

$str
都被分配了一个单引号(即非插值)目标行,以插入到OP的第一行文本之后。两个答案都使用
\nnewtextline
插入新文本行(即
\n
已针对两种语言正确插入)。

  • 在 Perl 中,
    s///
    运算符的 RHS(识别域)实际上是一个双引号字符串。因此,要禁用正则表达式插值,必须使用
    \Q … \E
    形式。请注意,Raku 需要
    my
    关键字,并且最好使用方括号。
  • 在 Raku 中,
    Q
    是最简单的引用结构:即使反斜杠会截断字符串,也不会被接受(如果你想转义内部反斜杠,请使用
    q
    )。

对于每种语言的第一个答案,识别的字符串将替换为匹配变量,即 Perl 中的

$&
和 Raku 中的
$/

对于每种语言的第二个答案,使用枚举捕获。在这两种语言中,

()
括号用于表示枚举捕获;请注意,Raku 中的捕获是从
$0
开始的。


示例输入:

<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>

示例输出(所有四个代码示例):

<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

© www.soinside.com 2019 - 2024. All rights reserved.