使用linux中的sed inplace editing替换包含某个字符串的行下面的特定行

时间:2012-03-28 15:26:12

标签: linux sed edit

我正在尝试编写文件的自动输入脚本,如下所示

*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE
$#     cid                                                                 title
$#    ssid      msid     sstyp     mstyp    sboxid    mboxid       spr       mpr
     1         2         3         3         0         0         0         0
$#      fs        fd        dc        vc       vdc    penchk        bt        dt
0.0100          0.000     0.000     0.000     0.000         0     0.000 1.0000E+7
$#     sfs       sfm       sst       mst      sfst      sfmt       fsf       vsf
1.000000  1.000000     0.000     0.000  1.000000  1.000000  1.000000  1.000000
*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE
$#     cid                                                                 title
$#    ssid      msid     sstyp     mstyp    sboxid    mboxid       spr       mpr
     1         3         3         3         0         0         0         0
$#      fs        fd        dc        vc       vdc    penchk        bt        dt
0.0100          0.000     0.000     0.000     0.000         0     0.000 1.0000E+7
$#     sfs       sfm       sst       mst      sfst      sfmt       fsf       vsf
1.000000  1.000000     0.000     0.000  1.000000  1.000000  1.000000  1.000000

我想在字符串

之后更改第五行
 *CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE

使用其他文件中的一行frictionValues.txt

我正在使用的内容如下

sed -i -e '/^\*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE/{n;n;n;n;n;R frictionValues.txt' -e 'd}' input.txt

但这会更改字符串后的所有5行,但它会从文件frictionValues.txt中读取值2次。我希望它只读取第一行,然后在找到字符串的所有实例中复制它。任何人都可以告诉我使用sed进行像这样的现场编辑吗?

3 个答案:

答案 0 :(得分:2)

试试这个:

frictionValues.txt的内容:

monday 
tuesday

input.txt的内容与您在问题中粘贴的内容相同。

script.sed的内容:

## Match literal string.
/^\*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE/ { 

    ## Append next five lines.
    N   
    N   
    N   
    N   
    N   

    ## Delete the last one.
    s/\(^.*\)\n.*$/\1/

    ## Print the rest of lines.
    p   

    ## Queue a line from external file.
    R frictionValues.txt

    ## Read next line (it will the external one).
    b   
}

## Print line.
p

像以下一样运行:

sed -nf script.sed input.txt

以下结果:

*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE
$#     cid                                                                 title
$#    ssid      msid     sstyp     mstyp    sboxid    mboxid       spr       mpr
     1         2         3         3         0         0         0         0
$#      fs        fd        dc        vc       vdc    penchk        bt        dt
monday 
$#     sfs       sfm       sst       mst      sfst      sfmt       fsf       vsf
1.000000  1.000000     0.000     0.000  1.000000  1.000000  1.000000  1.000000
*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE
$#     cid                                                                 title
$#    ssid      msid     sstyp     mstyp    sboxid    mboxid       spr       mpr
     1         3         3         3         0         0         0         0
$#      fs        fd        dc        vc       vdc    penchk        bt        dt
tuesday
$#     sfs       sfm       sst       mst      sfst      sfmt       fsf       vsf
1.000000  1.000000     0.000     0.000  1.000000  1.000000  1.000000  1.000000

答案 1 :(得分:2)

这可能对你有用(关于你想要的东西我可能完全没有了!):

sed '1s|.*|1{x;s/^/&/;x};/^\*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE/{n;n;n;n;n;G;s/.*\\n//}|;q' frictionValues.txt |
sed -i -f - input.txt

说明:

  • sed的第一行构建一个frictionValues.txt脚本,该脚本将所述第一行填入保留空间(HS)。剩下的脚本与以前一样,但使用R frictionValues.txt而不是G将HS附加到模式空间。
  • 使用sed开关对input.txt文件运行上述-f -脚本,sed脚本通过前一个管道中的stdin传递。

答案 2 :(得分:1)

我采取了两步的方法: 首先找出具有匹配文本的行号:

linenum=`grep -m 1 \*CONTACT_FORMING_ONE_WAY_SURFACE_TO_SURFACE input.txt | awk '{print $1}'`

现在,根据行号组合sed命令进行替换。 使用“frictionValues.txt”中的值更改在linenum + 5处的数据 - 并且还删除在linenum + 5处的数据

sed -e "$((linenum+5)) c `cat frictionValues.txt`" -e "$((linenum+5)) d" input.txt

<强>假设

frictionValues.txt - 只有一行

您使用的是现代Linux操作系统之一