评估 sed 中替换内捕获的表达式

评估 sed 中替换内捕获的表达式

我正在开发部署脚本,我的需要是替换配置文件中的数据库(或其他系统)凭据。

我有带有如下凭据的 PHP 文件:

<?php

return [
    'mysql-rw' => [
      'dns' => 'mysql-rw.local',
      'user' => 'local',
      'password' => 'PASS__LABELONE__',
    ],
    'mysql-ro' => [
      'dns' => 'mysql-ro.local',
      'user' => 'local',
      'password' => 'PASS__LABELTWO__',
    ],
];

我还在 CI 服务器中设置了 Bash 环境变量 -LABELONELABELTWO.我想用一行sed命令替换文件中的模板,但有错误或替换错误:

LABELONE=pass1 LABELTWO=pass2 sed -r "s/PASS__(.+)__/${!\1}/" tst.txt 
bash: s/PASS__(.+)__/${!\1}/: bad substitution

我的方法是:

  1. 在文件中查找模板
  2. 从中捕获标签(在 PASS__LBL__ 中它是 LBL)
  3. 将模板替换为 env。变量($LBL)

我怎样才能评估这样的动态变量,sed或者它是不真实的?

答案1

Perl 可以通过 %ENV 哈希访问 env 变量:

LABELONE=pass1 LABELTWO=pass2 perl -pe 's/PASS__(.+)__/$ENV{$1}/' -- tst.txt

答案2

(...)从表达式捕获的组的值sed无法动态处理巴什环境变量,使用GNUawk改为程序:

export LABELONE="pass1"
export LABELTWO="pass2"

awk 'match($0, /PASS__([^_]+)__/, m){ sub(/PASS__[^_]+__/, ENVIRON[m[1]]) }1' testfile

输出:

<?php

return [
    'mysql-rw' => [
      'dns' => 'mysql-rw.local',
      'user' => 'local',
      'password' => 'pass1',
    ],
    'mysql-ro' => [
      'dns' => 'mysql-ro.local',
      'user' => 'local',
      'password' => 'pass2',
    ],
];

ENVIRON
包含环境值的关联数组。数组索引是环境变量名称;元素是特定环境变量的值。

答案3

可能不是您正在寻找的,但是如果您通过多个 sed 顺序通过管道传递它,并显式匹配标签,它确实可以工作......当然不优雅。

LABELONE=pass1; LABELTWO=pass2;
sed -r "s/PASS__LABELONE__/$LABELONE/" tst.txt | sed -r "s/PASS__LABELTWO__/$LABELTWO/"

当然,如果您有更多变量或者它们被命名为其他名称,这很快就会变得乏味。你可能可以在 bash 本身中做一些事情,但不幸的是,我自己不知道如何在一行 sed 中做到这一点。

编辑:好吧,假设这些变量确实是环境变量并且您可以访问 envsubst,那么这是可行的

导出 LABLEONE=pass1

导出 LABELTWO=pass2

sed -r "s/PASS__(.+)__/$\1/g" test.txt | sed -r "s/PASS__(.+)__/$\1/g" test.txt |环境替换

然而,它依赖于 envsubst,我认为这是 gettext 的一部分。那么不知道这是否适合你?另外,通过在配置文件中写入实际的 $LABELONE 变量,您可以完全摆脱 sed 并只使用 envsubst。就我个人而言,我喜欢另一条评论中提到的 perl 脚本,所以我投了赞成票。

相关内容