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

2024-10-22 08:28:00
admin
原创
58
摘要:问题描述:我有几个文本文件,其中引入了 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;

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

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用