envsubst不能进行就地替换吗?

pee*_*dee 5 bash environment-variables

我有一个配置文件,其中包含一些ENV_VARIABLE样式的变量.

This is my file.
It might contain $EXAMPLES of text.
Run Code Online (Sandbox Code Playgroud)

现在我希望将该变量替换为保存在我的实际环境变量中的值.所以我正在尝试这个:

export EXAMPLES=lots
envsubst < file.txt > file.txt
Run Code Online (Sandbox Code Playgroud)

但是当输入文件和输出文件相同时它不起作用.结果是一个大小为0的空文件.

必须有一个很好的理由,一些我不知道的bash基础知识?如何在不首先输出到其他文件然后用它替换原始文件的情况下实现我想要做的事情?

我知道我可以轻松地完成它sed,但当我发现envsubst命令时,我认为它应该是我的用例的完美,所以我想使用它.

igo*_*ops 22

要避免创建临时文件,请使用spongenot tee:

envsubst < file.txt | sponge file.txt
Run Code Online (Sandbox Code Playgroud)

来自https://linux.die.net/man/1/sponge:

Sponge 读取标准输入并将其写入指定文件。与 shell 重定向不同,sponge 在打开输出文件之前吸收所有输入。这允许限制读取和写入同一文件的管道。

  • 美丽,我以前从未听说过这个。这是特定于任何 shell 或发行版的吗?或者这也适用于 GNU 和 Mac 吗? (4认同)
  • @peedee [sponge 二进制](https://command-not-found.com/sponge) 是 `moreutils` 包的一部分 (3认同)

Sof*_*tor 12

这是我使用的解决方案:

originalfile="file.txt"
tmpfile=$(mktemp)
cp --attributes-only --preserve $originalfile $tmpfile
cat $originalfile | envsubst | tee $tmpfile &&  mv $tmpfile $originalfile
Run Code Online (Sandbox Code Playgroud)

小心其他不使用临时文件的解决方案。管道是异步的,因此文件在tee截断后偶尔会被读取。


小智 12

我找到了另一个放入临时文件的快捷方式,然后将其重命名为原始文件。

envsubst < in.txt > out.txt && mv out.txt in.txt
Run Code Online (Sandbox Code Playgroud)


ric*_*ici 8

重定向由shell处理,而不是正在执行的程序,并且在调用程序之前设置它们.

重定向>output.file具有创建的效果,output.file如果它不存在并且如果它存在则将其清空.无论哪种方式,最终都会得到一个空文件,这就是程序输出重定向到的内容.

程序,如sed其中"就地"修饰的能够一定要把文件名作为命令行参数,而不是作为一个重定向.

在你的情况下,我建议使用一个临时文件,然后重命名它,如果一切正常.


小智 7

envsubst < file.txt | tee file.txt
Run Code Online (Sandbox Code Playgroud)

  • 小心这个答案。它有一个竞争条件。管道是异步的,因此 envsubst 偶尔会在 tee 截断文件后读取该文件。尝试运行以下实验 - 您将看到您的文件将变空:```for i in {0..1000}; 执行 envsubst &lt; file.txt | tee文件.txt;完成``` (11认同)