bash - 从命令行查找和替换多行文本

标签 bash awk sed

我正在尝试使用同时执行其他操作的脚本来编辑配置文件。

脚本需要找到某些连续的文本行并将其删除。 它需要从旧配置所在的同一行开始粘贴新配置。在旧配置和新配置中,空格的使用都很重要。

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

对于其他 awk 来说,它是:

$ 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

关于bash - 从命令行查找和替换多行文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43851572/

相关文章:

bash - [[ -s "$HOME/.rvm/scripts/rvm"]] && 。 "$HOME/.rvm/scripts/rvm": What does it do?

linux - 带有 put *.* 的 ftp 命令不发送所有文件

Linux awk 打印某些文本

regex - 从 shell 脚本中的字符串中过滤非字母字符

regex - 如何使用 sed 按正则表达式对行进行排序

bash - 如何使用 AWK 或 SED 在第 N 行之前打印字符串并从第 N 行删除特定字符串

bash - 剥离管道输出的第一部分

regex - 如何替换与 egrep 匹配的较大字符串中的子字符串?

linux - 在 Linux 中用 sed 替换点、感叹号和问号

linux - 通过指定行号显示单行?