Linux 如何在复杂文本文件中替换shell变量
我有几个文本文件,其中引入了shell变量($VAR1或$VAR2) 我想把这些文件(一个接一个)保存在新文件中,所有变量都会被替换 为此,我使用了以下shell脚本(在StackOverflow上找到):Linux 如何在复杂文本文件中替换shell变量,linux,shell,string-interpolation,Linux,Shell,String Interpolation,我有几个文本文件,其中引入了shell变量($VAR1或$VAR2) 我想把这些文件(一个接一个)保存在新文件中,所有变量都会被替换 为此,我使用了以下shell脚本(在StackOverflow上找到): 读取行时 做 eval echo“$line”>>destination.txt 完成destination.txt
读取行时
做
eval echo“$line”>>destination.txt
完成<“source.txt”
这在非常基本的文件上非常有效
但在更复杂的文件上,“eval”命令的作用太大:
- 将跳过以“#”开头的行
- XML文件解析会导致大量错误
如果您真的只想使用bash(和sed),那么我将检查您的每个环境变量(在posix模式下由
set
返回),并从中为sed构建一组-e'regex'
,以-e's/\$[a-zA-Z][a-zA-Z0-9*///g'
结尾,然后将所有这些传递给sed
不过,Perl会做得更好,您可以作为数组访问环境变量,并且可以执行可执行替换,因此只需匹配任何环境变量一次。实际上,您需要将
read
更改为read-r
,这将使它忽略反斜杠
此外,还应该对引号和反斜杠进行转义。
所以
读取-r行时;做
line=“${line/\\/\\\}”
line=“${line/\”/\\\“}”
line=“${line/\`/\\\`}”
评估回音“\”$line“
完成>destination.txt
不过,进行扩展仍然是一种糟糕的方式。看起来,在我的系统中,有一个命令是gettext base包的一部分 因此,这样做很容易:
envsubst < "source.txt" > "destination.txt"
envsubst<“source.txt”>“destination.txt”
注意:如果您想对这两个文件使用相同的文件,则必须使用类似于moreutil的
海绵
,正如Johnny Utahh所建议的那样:envsubt
。(因为shell重定向将在读取文件之前清空文件。)在回答2时,在讨论envsubt时,您询问:
如何使它与在.sh脚本中声明的变量一起工作
答案是您只需在调用envsubt
之前导出变量即可
您还可以使用envsubt
SHELL\u FORMAT
参数限制要在输入中替换的变量字符串(避免用公共SHELL变量值意外替换输入中的字符串-例如$HOME
)
例如:
export VAR1='somevalue' VAR2='someothervalue'
MYVARS='$VAR1:$VAR2'
envsubst "$MYVARS" <source.txt >destination.txt
export VAR1='somevalue'VAR2='someothervalue'
MYVARS='$VAR1:$VAR2'
envsubs“$MYVARS”destination.txt
将分别用
'somevalue'
和'someothervalue'
替换source.txt
中$VAR1
和$VAR2
的所有实例(并且只有VAR1
和VAR2
)看起来和我想使用的东西一模一样,但是-v
选项让我有点吃惊
虽然envsubt
工作正常,但选项-v
的相同功能不起作用:
$ envsubst -v < template.txt
envsubst: missing arguments
$ cat template.txt | envsubst -v
envsubst: missing arguments
$cat/etc/redhat版本
Red Hat Enterprise Linux Server 7.1版(Maipo)
$envsubst-V
envsubst(GNU gettext运行时)0.18.2
版权所有(C)2003-2007自由软件基金会。
许可证GPLv3+:GNU GPL版本3或更高版本
这是自由软件:您可以自由更改和重新发布它。
在法律允许的范围内,不存在任何担保。
布鲁诺·海布尔写的。
正如我所写,这是行不通的:
$ envsubst -v < template.txt
envsubst: missing arguments
$ cat template.txt | envsubst -v
envsubst: missing arguments
也许它对某人有帮助。导出所有需要的变量,然后使用perl联机程序
TEXT=$(echo“$TEXT”| perl-wpne的#\${(\w+)}?#$ENV{$1}/$ge;')
这将用实际值替换文本中的所有环境变量。
还保留了引号:)
$export MY\u ENV\u VAR=祝贺
$MY\u ENV\u VAR
您还可以使用系统定义的所有其他ENV变量,如(在linux中)$TERM、$SHELL、$HOME
$envsubst“`printf'${%s}'$(sh-c“env|cut-d'='-f1”)``out.txt
$cat out.txt
您应该会看到“祝贺”。我知道这个主题很古老,但我有一个更简单的工作解决方案,不需要导出变量。可以是一行,但我更喜欢在行尾使用
\
进行拆分
var1='myVar1'\
var2=2\
var3=${var1}\
envsubst '$var1,$var3' < "source.txt" > "destination.txt"
# ^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^
# define which to replace input output
var1='myVar1'\
var2=2\
var3=${var1}\
envsubt“$var1,$var3”<“source.txt”>“destination.txt”
# ^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^
#定义要替换的输入输出
需要将变量定义为与envsubt
相同的行,以便将其视为环境变量
“$var1,$var3”
是可选的,只能替换指定的变量。假设一个输入文件包含不应该被替换的${VARIABLE\u USED\u BY_JENKINS}
。如果您希望在源文件中替换环境变量,同时保持所有非环境变量不变,可以使用以下命令:
envsubst“$(printf'${%s}'$(env | sed's/=.*/'))”destination.txt
仅替换特定变量的语法为。上面的命令使用一个子shell列出所有定义的变量,然后将其传递给envsubt
因此,如果定义了一个名为$NAME
的env变量,并且您的source.txt
文件看起来是l
var1='myVar1'\
var2=2\
var3=${var1}\
envsubst '$var1,$var3' < "source.txt" > "destination.txt"
# ^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^
# define which to replace input output
Hello $NAME
Your balance is 123 ($USD)
Hello Arik
Your balance is 123 ($USD)
perl -pi -e 'foreach $key(sort keys %ENV){ s/\$$key/$ENV{$key}/g}' file
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)