如何在复杂文本文件中替换 shell 变量

2024-10-22 08:28:00
admin
原创
255
摘要:问题描述:我有几个文本文件,其中引入了 shell 变量(例如 $VAR1 或 $VAR2)。我想(逐个)获取这些文件并将它们保存到新文件中,其中所有变量都将被替换。为此,我使用了以下 shell 脚本(在 StackOverflow 上找到):while read line do eval echo...

问题描述:

我有几个文本文件,其中引入了 shell 变量(例如 $VAR1 或 $VAR2)。

我想(逐个)获取这些文件并将它们保存到新文件中,其中所有变量都将被替换。

为此,我使用了以下 shell 脚本(在 StackOverflow 上找到):

while read line
do
    eval echo "$line" >> destination.txt
done < "source.txt"

这对于非常基本的文件非常有效。

但是对于更复杂的文件,“eval”命令的作用就太大了:

  • 跳过以“#”开头的行

  • XML 文件解析导致大量错误

有没有更好的方法呢?(在 shell 脚本中...我知道例如用 Ant 就可以轻松完成)

亲切的问候


解决方案 1:

经查看,发现我的系统上有一个envsubst命令,它是 gettext-base 包的一部分。

因此,这变得简单:

envsubst < "source.txt" > "destination.txt"

请注意,如果您想对两者使用相同的文件,则必须使用 moreutil 之类的东西sponge,正如 Johnny Utahh 所建议的那样:envsubst < "source.txt" | sponge "source.txt"。(因为 shell 重定向会在读取之前清空文件。)

解决方案 2:

参考答案 2,在讨论 envsubst 时,您问道:

我如何使其与我的 .sh 脚本中声明的变量一起工作?

答案是您只需要在调用之前导出变量envsubst

您还可以使用参数限制要在输入中替换的变量字符串envsubst SHELL_FORMAT(避免用常见的 shell 变量值意外替换输入中的字符串 - 例如$HOME)。

例如:

export VAR1='somevalue' VAR2='someothervalue'
MYVARS='$VAR1:$VAR2'

envsubst "$MYVARS" <source.txt >destination.txt

将分别用和替换 中的所有$VAR1$VAR2(且仅VAR1VAR2)实例。source.txt`'somevalue'`'someothervalue'

解决方案 3:

我知道这个主题已经过时了,但我有一个更简单的解决方案,无需导出变量。可以是一行代码,但我更喜欢使用``行尾进行拆分。

var1='myVar1'\nvar2=2\nvar3=${var1}\nenvsubst '$var1,$var3' < "source.txt" > "destination.txt"

#         ^^^^^^^^^^^    ^^^^^^^^^^     ^^^^^^^^^^^^^^^
# define which to replace   input            output

变量需要定义到同一行envsubst才能被视为环境变量。

可选'$var1,$var3'的仅替换指定的。想象一下包含${VARIABLE_USED_BY_JENKINS}不应替换的输入文件。

解决方案 4:

  1. 定义 ENV 变量

$ export MY_ENV_VAR=congratulation
  1. 创建模板文件(in.txt),内容如下

$MY_ENV_VAR

您还可以使用系统定义的所有其他 ENV 变量,如(在 Linux 中)$TERM、$SHELL、$HOME……

  1. 运行此命令替换in.txt文件中的所有环境变量,并将结果写入out.txt

$ envsubst "`printf '${%s} ' $(sh -c "env|cut -d'=' -f1")`" < in.txt > out.txt
  1. 检查out.txt文件的内容

$ cat out.txt

您应该会看到“祝贺”。

解决方案 5:

还有这个选项:

在文件中定义变量

$ cat variables.env 
# info about what this var is
export var1=a
# info about var again
export var2=b

定义使用变量的模板文件

$ cat file1-template.txt
This is var1: "${var1}"
This is var2: "${var2}"

生成最终文件,将变量替换为值

$ source variables.env
$ envsubst < file1-template.txt > file1.txt
$ cat file1.txt 
This is var1: "a"
This is var2: "b"

解决方案 6:

如果您希望在源文件中替换环境变量,同时保留所有非环境变量,则可以使用以下命令:

envsubst "$(printf '${%s} ' $(env | sed 's/=.*//'))" < source.txt > destination.txt

此处解释了仅替换特定变量的语法。上面的命令使用子 shell 列出所有定义的变量,然后将其传递给envsubst

因此,如果有一个名为的定义的环境变量$NAME,并且您的source.txt文件如下所示:

Hello $NAME
Your balance is 123 ($USD)

destination.txt是:

Hello Arik
Your balance is 123 ($USD)

请注意,$NAME被替换,$USD保持不变

解决方案 7:

while IFS='=' read -r name value ; do
    # Print line if found variable
    sed -n '/${'"${name}"'}/p' docker-compose.yml
    # Replace variable with value. 
    sed -i 's|${'"${name}"'}|'"${value}"'|' docker-compose.yml
done < <(env)

注意:变量名称或值不应包含“|”,因为它用作分隔符。

解决方案 8:

实际上,您需要将您的更改readread -r,以使其忽略反斜杠。

另外,你应该转义引号和反斜杠。所以

while read -r line; do
  line="${line//\\/\\\\}"
  line="${line//\"/\\\"}"
  line="${line//`/\\`}"
  eval echo "\"$line\""
done > destination.txt < source.txt

但仍然是一种糟糕的扩张方式。

解决方案 9:

如果您真的只想使用 bash(和 sed),那么我会遍历您的每个环境变量(如在 posix 模式下返回的)并从中set构建一堆for sed,以 终止,然后将所有这些传递给 sed。-e 'regex'`-e 's/$a-zA-Z_*//g'`

然而,Perl 可以做得更好,您可以将环境变量作为数组访问,并可以进行可执行替换,因此您只需匹配任何环境变量一次。

解决方案 10:

导出所有需要的变量,然后使用 perl onliner

TEXT=$(echo "$TEXT"|perl -wpne 's#${?(w+)}?# $ENV{$1} // $& #ge;')

这将用实际值替换 TEXT 中存在的所有 ENV 变量。引号也会被保留 :)

解决方案 11:

-pi通过在单引号中运行 perl 代码( the ),调用 perl 二进制文件,以按行搜索和替换模式( the )进行搜索和替换-e,该代码遍历包含导出的变量名作为键、导出的变量值作为键值的特殊哈希的键,并且每次迭代都简单地用其%ENV替换包含 的字符串。$&lt;&lt;key>>`<<value>>`

 perl -pi -e &#039;foreach $key(sort keys %ENV){ s/$$key/$ENV{$key}/g}&#039; file

警告:当两个或多个变量以相同的字符串开头时,需要额外的逻辑处理...

解决方案 12:

这是递归变量替换:

#!/bin/sh
find ./abc -type f | while read file; 
do  
   FF=&quot;$file&quot;;
   envsubst &lt; ${FF} > ${FF}.replaced
   rm ${FF}
   mv ${FF}.replaced ${FF}
   echo &quot;Replacing ${FF}&quot;
done

解决方案 13:

envsubst看起来正是我想要用的东西,但是-v选项让我有点惊讶。

虽然envsubst &lt; template.txt运行正常,但相同选项-v不起作用:

$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.1 (Maipo)
$ envsubst -V
envsubst (GNU gettext-runtime) 0.18.2
Copyright (C) 2003-2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later &lt;http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Bruno Haible.

正如我所写的,这是行不通的:

$ envsubst -v &lt; template.txt
envsubst: missing arguments
$ cat template.txt | envsubst -v
envsubst: missing arguments

我必须这样做才能让它发挥作用:

TEXT=`cat template.txt`; envsubst -v &quot;$TEXT&quot;

也许它能对某些人有帮助。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2560  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1552  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审与决策评审是IPD流程中至关重要的环节,它们既有明显的区别,又存在紧密的协同关系。深入理解这两者的区别与协同,对于企业有效实施IPD流程,提升产品开发效率与质量具有重要意义...
IPD管理流程   1  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、ClickUp、Freshdesk、GanttPRO、Planview、Smartsheet、Asana、Nifty、HubPlanner、Teamwork。在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目按时交付的关键工具。然而...
项目管理系统   2  
  建设工程项目质量关乎社会公众的生命财产安全,也影响着企业的声誉和可持续发展。高质量的建设工程不仅能为使用者提供舒适、安全的环境,还能提升城市形象,推动经济的健康发展。在实际的项目操作中,诸多因素会对工程质量产生影响,从规划设计到施工建设,再到后期的验收维护,每一个环节都至关重要。因此,探寻并运用有效的方法来提升建设工程...
工程项目管理制度   3  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用