Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何在复杂文本文件中替换shell变量_Linux_Shell_String Interpolation - Fatal编程技术网

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

Linux 如何在复杂文本文件中替换shell变量,linux,shell,string-interpolation,Linux,Shell,String Interpolation,我有几个文本文件,其中引入了shell变量($VAR1或$VAR2) 我想把这些文件(一个接一个)保存在新文件中,所有变量都会被替换 为此,我使用了以下shell脚本(在StackOverflow上找到): 读取行时 做 eval echo“$line”>>destination.txt 完成destination.txt

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

我想把这些文件(一个接一个)保存在新文件中,所有变量都会被替换

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

读取行时
做
eval echo“$line”>>destination.txt
完成<“source.txt”
这在非常基本的文件上非常有效

但在更复杂的文件上,“eval”命令的作用太大:

  • 将跳过以“#”开头的行

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

有更好的方法吗?(在shell脚本中…我知道这很容易用Ant实现)


如果您真的只想使用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=祝贺
    
  • 使用以下内容创建模板文件(in.txt
  • $MY\u ENV\u VAR
    
    您还可以使用系统定义的所有其他ENV变量,如(在linux中)$TERM、$SHELL、$HOME

  • 运行此命令将所有环境变量替换到in.txt文件中,并将结果写入out.txt
  • $envsubst“`printf'${%s}'$(sh-c“env|cut-d'='-f1”)``out.txt
    
  • 检查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)