【问题标题】:How to use sed in shell script to replace all environment value occurrences with their current values如何在 shell 脚本中使用 sed 将所有出现的环境值替换为其当前值
【发布时间】:2020-01-14 07:39:09
【问题描述】:

我想要一个 shell 脚本来遍历文件中所有出现的环境变量名称,并用它们的当前值替换它们。我不确定如何使用sed 命令来完成此操作。

文件内容:

values:
  value1: 
    name: "something"
    value: "$ENV_VAR1" # this could be any variable name
  value2: 
    name: "something"
    value: "$ENV_VAR2" 
...

首先,我需要找到所有出现的任何变量(使用正则表达式 "\$(.*?)" )。然后,不知何故,我需要用 shell 中的变量值替换它。我不确定如何使用sed 命令来实现第二部分,因为变量名是在文件本身中指定的。

类似于以下命令:

sed -i "s/\"\$(.*?)\"/${Some_How_Get_Var_Name}/g" file.yaml 

【问题讨论】:

  • 这是一个 YAML 文件吗?建议使用适当的语言感知解析器,如yq
  • perl -pe 'while (my ($k, $v) = each %ENV) { s/\$$k/$v/g }'
  • @Inian 是的,它是一个 yaml 文件。我在一个 bash 非常有限的基本高山图像上运行它。

标签: regex shell sed


【解决方案1】:

如果您使用bash 并且envsubst 命令可用,您可以这样做:

 envsubst < inputfile

例如(创建一个临时输入来演示它:

$ env | tail -2 | sed 's_^_$_'
$MANPATH=/home/linuxbrew/.linuxbrew/share/man:
$INFOPATH=/home/linuxbrew/.linuxbrew/share/info:

然后通过envsubst运行这个:

$ env | tail -2 | sed 's_^_$_' | envsubst
/home/linuxbrew/.linuxbrew/share/man:=/home/linuxbrew/.linuxbrew/share/man:
/home/linuxbrew/.linuxbrew/share/info:=/home/linuxbrew/.linuxbrew/share/info:

【讨论】:

【解决方案2】:

这是一个经常出现的问题。 envsubst 通常作为解决方案提供,但我发现坚持使用 perl 并执行以下操作会更容易:

perl -pe 'while (my ($k, $v) = each %ENV) { s/\$$k/$v/g }'

这几乎肯定不是一个可靠的解决方案(它将替换 $FOO,但它不会替换 ${FOO} 的形式),但我发现我总是对 envsubst 不这样做感到失望${FOO-bar}envsubst 似乎不如 perl 无处不在。

或者,与其替换环境中的所有内容,您可能更喜欢以下内容:

perl -pe 's/\$([[:alpha:]_][_[:alnum:]]+)/$ENV{$1}/g'

perl -pe 's/\$([[:alpha:]_][\w]+)/$ENV{$1}/g'

如果 FOO 未定义,最后两个将用空字符串替换 '$FOO',而第一个不替换它。您希望哪种行为可能会决定使用哪种行为。

我不会声称这些是完全正确的,但它们是一个合理的近似值。

【讨论】:

    【解决方案3】:

    这可能对你有用(GNU sed):

    sed '/value:/{y/"/\n/;s/^.*/printf "&"/e;y/\n/"/}' file
    

    在包含字符串value: 的任何行上,将任何" 转换为换行符,使用printf 将环境变量转换为其实际值,并将引入的换行符重新转换回"

    注意如果环境变量可以包含",则需要在 printf 命令之后引用它们,即在最后一个y 命令之前插入s/"/\\"/g

    【讨论】:

      【解决方案4】:

      这是一个awk 解决方案(标准 Gnu Linux awk)。

      准备环境

      export ENV_VAR1=var1
      export ENV_VAR2=var2
      

      input.txt

      values:
        value1: 
          name: "something"
          value: "$ENV_VAR1" # this could be any variable name
        value2: 
          name: "something"
          value: "$ENV_VAR2" 
      ...
      

      运行:

      awk 'BEGIN{FPAT="\\$[^\"]+"}{sub(FPAT,ENVIRON[substr($1,2)])}1' input.txt
      

      输出.txt

      values:
        value1:
          name: "something"
          value: "env1" # this could be any variable name
        value2:
          name: "something"
          value: "env2"
      ...
      

      说明:

      BEGIN{ # pre-processing
          FPAT="\\$[^\"]+"; # assign RegExp to identify the environemnt vairable as field
      }
      { # for each input line
          envVarName = substr($1,2); # extract the environment variable name from 1st input field
          envVarValue = ENVIRON[envVarName]; # assign environment variable value from envVarName
          sub(FPAT,envVarValue); # subsitute 1st field with envVarValue
      }
      1 # print each input line
      

      【讨论】:

      • 它工作正常,但由于某种原因无法获取环境变量。这可能是在 awk 命令中无法访问环境变量的方式。 ENVIRON[envVarName] 总是返回空。
      • 其实我错了。 substr($1,2) 没有按预期工作。
      • 确保环境变量已导出。否则子 shell 无法访问它们。尝试bash -c env |grep -i env 测试您的环境变量气泡到子外壳。
      • 不,环境变量没问题。问题在于 substr 函数,由于某种原因,它给了我一个非常奇怪的输出。 env var 的名称选择不正确。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-08
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 2014-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多