bash envsubst 可以不进行就地替换吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35078753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 14:10:37  来源:igfitidea点击:

Can envsubst not do in-place substitution?

bashenvironment-variables

提问by peedee

I have a config file which contains some ENV_VARIABLE styled variables.

我有一个包含一些 ENV_VARIABLE 样式变量的配置文件。

This is my file.
It might contain $EXAMPLES of text.

Now I want that variable replaced with a value which is saved in my actual environment variables. So I'm trying this:

现在我想用保存在我的实际环境变量中的值替换该变量。所以我正在尝试这个:

export EXAMPLES=lots
envsubst < file.txt > file.txt

But it doesn't work when the input file and output file are identical. The result is an empty file of size 0.

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

There must be a good reason for this, some bash basics that I'm not aware of? How do I achieve what I want to do, ideally without first outputting to a different file and then replacing the original file with it?

这一定有一个很好的理由,一些我不知道的 bash 基础知识?我如何实现我想要做的事情,最好不要先输出到不同的文件,然后用它替换原始文件?

I know that I can do it easily enough with sed, but when I discovered the envsubstcommand I thought that it should be perfect for my use case, so I'd like to use that.

我知道我可以很容易地使用sed,但是当我发现该envsubst命令时,我认为它应该非常适合我的用例,所以我想使用它。

回答by rici

Redirects are handled by the shell, not the program being executed, and they are setup before the program is invoked.

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

The redirect >output.filehas the effect of creating output.fileif it doedn't exist and emptying it if it does. Either way, you end up with an empty file, and that is what the program's output is redirected to.

重定向>output.file的作用是output.file在它不存在时创建,如果存在则清空它。无论哪种方式,您最终都会得到一个空文件,这就是程序的输出被重定向到的地方。

Programs like sedwhich are capable of "in-place" modification must take the filename as a command-line argument, not as a redirect.

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

In your case, I would suggest using a temporary file and then renaming it if all went OK.

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

回答by Laine Damien

envsubst < file.txt | tee file.txt

回答by SoftwareFactor

Here is the solution that I use:

这是我使用的解决方案:

tmpfile=$(mktemp)
cat file.txt | envsubst | tee "$tmpfile" &&  mv "$tmpfile" file.txt

Be careful with other solutions that do not use a temporary file. Pipes are asynchronous, so the file will occasionally be read after teehas already truncated it.

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

回答by Christoph H?sler

You can achieve in-place substitution by calling envsubst from gnu sed with the "e" command:

您可以通过使用“e”命令从 gnu sed 调用 envsubst 来实现就地替换:

EXAMPLES=lots sed -i 's/.*/echo & | envsubst/e' file.txt

回答by peedee

In the end I found that using envsubstwas too dangerous after all. My files might contain dollar signs in places where I don't want any substitution to happen, and envsubstwill just replace them with empty strings if no corresponding environment variable is defined. Not cool.

最后我发现使用envsubst毕竟太危险了。我的文件可能在我不希望发生任何替换的地方包含美元符号,envsubst如果没有定义相应的环境变量,我只会用空字符串替换它们。不酷。