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

Ben*_*Ben 61 linux shell

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

我想将这些文件(逐个)保存在新文件中,其中所有变量都已被替换.

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

while read line
do
    eval echo "$line" >> destination.txt
done < "source.txt"
Run Code Online (Sandbox Code Playgroud)

这在非常基本的文件上非常有效.

但是对于更复杂的文件,"eval"命令做得太多了:

  • 以"#"开头的行将被跳过

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

有没有更好的方法呢?(在shell脚本中......我知道这很容易用Ant完成)

亲切的问候

der*_*ert 144

看,结果在我的系统上有一个envsubst命令,它是gettext-base包的一部分.

所以,这很容易:

envsubst < "source.txt" > "destination.txt"
Run Code Online (Sandbox Code Playgroud)

  • @Ben:对你要在envsubst中使用的每个变量使用'export'(在调用envsubst之前) (7认同)
  • `envsubst`是[GNU gettext]的一部分(https://www.gnu.org/software/gettext/manual/html_node/envsubst-Invocation.html) (6认同)
  • 大!但它仅适用于环境变量.如何使用我的.sh脚本中声明的变量? (4认同)
  • 警告:如果 `source.txt` 包含变量扩展之外的任何 `$` 字符,`envsubst` 也会替换这些字符,并且无法转义 `$`。常见(丑陋)的解决方法是`export DOLLAR="$"`。 (4认同)
  • @user_mda输出的位置. (3认同)
  • 如果您想就地编辑文件: `envsubst &lt; "source.txt" | 使用 [sponge(1)](/sf/answers/468805361/) 的海绵“source.txt”`。 (2认同)
  • 如果没有海绵(轻量级环境中经常出现这种情况),您也可以使用子壳。请参阅此答案 https://serverfault.com/a/547331 (2认同)
  • 您还可以使用 `tee` 来替换文件: `envsubst &lt; "source.txt" | 三通“source.txt”` (2认同)

小智 49

在回答2时,在讨论envsubst时,你问"如何使用我的.sh脚本中声明的变量?"

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

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

例如:

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

envsubst "$MYVARS" <source.txt >destination.txt
Run Code Online (Sandbox Code Playgroud)

将source.txt中的$ VAR1和$ VAR2(以及仅VAR1和VAR2)的所有实例分别替换为'somevalue'和'someothervalue'.

  • 用于设置'MYVARS`的单引号''是至关重要的 (8认同)

ine*_*tom 10

我知道这个主题是旧的,但我有一个更简单的工作解决方案,而不导出变量.可以是oneliner,但我更喜欢\在线端分割.

var1='myVar1'\
var2=2\
var3=${var1}\
envsubst '$var1,$var3' < "source.txt" > "destination.txt"

#         ^^^^^^^^^^^    ^^^^^^^^^^     ^^^^^^^^^^^^^^^
# define which to replace   input            output
Run Code Online (Sandbox Code Playgroud)

需要将变量定义为与envsubst被视为环境变量的同一行.

'$var1,$var3'是可选的,只更换指定的.想象一下输入文件包含${VARIABLE_USED_BY_JENKINS}哪些不应该被替换.

  • 你救了我的命,秘密英雄,我不喜欢导出解决方案。谢谢 (2认同)
  • 谢谢,“$var1,$var3”提示真的很省时间 (2认同)

Rad*_*iel 10

还有这个选项:

在文件中定义变量

$ cat variables.env 
# info about what this var is
export var1=a
# info about var again
export var2=b
Run Code Online (Sandbox Code Playgroud)

定义使用变量的模板文件

$ cat file1-template.txt
This is var1: "${var1}"
This is var2: "${var2}"
Run Code Online (Sandbox Code Playgroud)

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

$ source variables.env
$ envsubst < file1-template.txt > file1.txt
$ cat file1.txt 
This is var1: "a"
This is var2: "b"
Run Code Online (Sandbox Code Playgroud)


Dad*_*ado 6

  1. 定义您的ENV变量
$ export MY_ENV_VAR=congratulation
Run Code Online (Sandbox Code Playgroud)
  1. 使用以下内容创建模板文件(in.txt
$MY_ENV_VAR
Run Code Online (Sandbox Code Playgroud)

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

  1. 运行此命令以放置in.txt文件中的所有环境变量并将结果写入out.txt
$ envsubst "`printf '${%s} ' $(sh -c "env|cut -d'=' -f1")`" < in.txt > out.txt
Run Code Online (Sandbox Code Playgroud)
  1. 检查out.txt文件的内容
$ cat out.txt
Run Code Online (Sandbox Code Playgroud)

您应该会看到“祝贺”。


Ari*_*rik 5

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

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

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

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

Hello $NAME
Your balance is 123 ($USD)
Run Code Online (Sandbox Code Playgroud)

destination.txt是:

Hello Arik
Your balance is 123 ($USD)
Run Code Online (Sandbox Code Playgroud)

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