bash – 从命令行查找并替换多行文本

我正在尝试使用也执行其他操作的脚本编辑配置文件.

该脚本需要找到某些连续的文本行并删除它们.
在适当的位置,它需要粘贴一个新配置,从与旧配置相同的行开始.在旧配置和新配置中,空间的使用很重要.

在configfile.php中,这个文本块:

  'session' => 
  array (
    'save' => 'files',
  ),

需要找到并替换为我在replacement.txt中放在同一位置的内容.

根据类似问题的答案,我尝试过的一件事是:

cat replacement.txt <(sed -i '1,/  'session' => \n  array (\n    'save' => 'files',\n  ),/d' configfile.php) > configfile.php

这导致一个空文件.

cat replacement.txt <(sed -i '1,/  'session' => \n  array (\n    'save' => 'files',\n  ),/d' configfile.php) > newfile.php

这与cat replacement.txt>相同. newfile.php,我想编辑一个文件,而不是创建一个新文件.

有谁知道我的语法有什么问题以及如何解决它?

我在here之前问过这个问题,但是我并没有完全理解自己想要什么,所以它有点过于复杂和令人困惑.我使用的是Debian Linux.

根据评论进行编辑:

replacement.txt看起来像这样:

  'session' =>
     array (
     'save' => 'redis',
     'redis' =>
        array (
          'host' => '127.0.0.1',
          'other_variable' => 'other_setting',
        )
     )
  ),

它已经按照应该的方式缩进,可以按原样插入.
使用awk或sed都很好.

最佳答案 使用GNU awk进行多字符RS:

$cat tst.awk
BEGIN { RS="^$"; ORS="" }
ARGIND==1 { old = $0 }
ARGIND==2 { new = $0 }
ARGIND==3 {
    if ( start = index($0,old) ) {
        $0 = substr($0,1,start-1) new substr($0,start+length(old))
    }
    print
}

$awk -f tst.awk target.txt replacement.txt configfile.php
  foo
  'session' =>
     array (
     'save' => 'redis',
     'redis' =>
        array (
          'host' => '127.0.0.1',
          'other_variable' => 'other_setting',
        )
     )
  ),
  bar

以上是在这些输入文件上运行的:

$cat  target.txt
  'session' =>
  array (
    'save' => 'files',
  ),
$
$cat replacement.txt
  'session' =>
     array (
     'save' => 'redis',
     'redis' =>
        array (
          'host' => '127.0.0.1',
          'other_variable' => 'other_setting',
        )
     )
  ),
$
$cat configfile.php
  foo
  'session' =>
  array (
    'save' => 'files',
  ),
  bar
$

与其他awks一样,它是:

$cat tst.awk
FNR==1 { ++argind }
argind==1 { old = (FNR>1 ? old RS : "") $0 }
argind==2 { new = (FNR>1 ? new RS : "") $0 }
argind==3 { rec = (FNR>1 ? rec RS : "") $0 }
END {
    if ( start = index(rec,old) ) {
        rec = substr(rec,1,start-1) new substr(rec,start+length(old))
    }
    print rec
}

$awk -f tst.awk target.txt replacement.txt configfile.php
  foo
  'session' =>
     array (
     'save' => 'redis',
     'redis' =>
        array (
          'host' => '127.0.0.1',
          'other_variable' => 'other_setting',
        )
     )
  ),
  bar
点赞