如何在文本文件中扩展shell变量?

Ken*_*war 15 unix bash shell ksh solaris

考虑一个ASCII文本文件(假设它包含非shell脚本语言的代码):

Text_File.msh:

spool on to '$LOG_FILE_PATH/logfile.log';
login 'username' 'password';
....
Run Code Online (Sandbox Code Playgroud)

现在,如果这是一个shell脚本,我可以运行它,$ sh Text_File.mshshell将自动扩展变量.我想要做的是让shell扩展这些变量,然后创建一个新文件Text_File_expanded.msh,如下所示:

Text_File_expanded.msh:

spool on to '/expanded/path/of/the/log/file/../logfile.log';
login 'username' 'password';
....
Run Code Online (Sandbox Code Playgroud)

考虑:

$ a=123
$ echo "$a"
123
Run Code Online (Sandbox Code Playgroud)

从技术上讲,这应该可以解决问题:

$ echo "`cat Text_File.msh`" > Text_File_expanded.msh
Run Code Online (Sandbox Code Playgroud)

...但它不能按预期工作,输出文件虽然与源相同.

所以我不确定如何实现这一点.我的目标是让我更容易维护嵌入在我的非shell脚本中的目录路径.这些脚本不能包含任何UNIX代码,因为它不是由UNIX shell编译的.

Dim*_*iev 27

这个问题已在另一个帖子中提出,这是IMO的最佳答案:

export LOG_FILE_PATH=/expanded/path/of/the/log/file/../logfile.log
cat Text_File.msh | envsubst > Text_File_expanded.msh
Run Code Online (Sandbox Code Playgroud)

如果在Mac上,请先安装gettext:brew install gettext

请参阅: 强制bash扩展从文件加载的字符串中的变量


Hai*_* Vu 9

这个解决方案不优雅,但它有效.创建一个脚本调用shell_expansion.sh:

echo 'cat <<END_OF_TEXT' >  temp.sh
cat "$1"                 >> temp.sh
echo 'END_OF_TEXT'       >> temp.sh
bash temp.sh >> "$2"
rm temp.sh
Run Code Online (Sandbox Code Playgroud)

然后,您可以调用此脚本,如下所示:

bash shell_expansion.sh Text_File.msh Text_File_expanded.msh
Run Code Online (Sandbox Code Playgroud)

  • 我发现 `echo -e "cat &lt;&lt;END_OF_TEXT\n$(cat [filename])\nEND_OF_TEXT" | bash` 在没有临时文件的情况下也能正常工作。 (2认同)

Gur*_*uru 9

如果Perl解决方案适合您:

样本文件:

$ cat file.sh
spool on to '$HOME/logfile.log';
login 'username' 'password';
Run Code Online (Sandbox Code Playgroud)

解:

$ perl -pe 's/\$(\w+)/$ENV{$1}/g' file.sh
spool on to '/home/user/logfile.log';
login 'username' 'password';
Run Code Online (Sandbox Code Playgroud)


Pau*_*ear 8

上述答案的一个限制是它们都需要将变量导出到环境中.以下是我提出的允许变量在当前shell脚本中的本地变量:

#!/bin/sh
FOO=bar;
FILE=`mktemp`; # Let the shell create a temporary file
trap 'rm -f $FILE' 0 1 2 3 15;   # Clean up the temporary file 

(
  echo 'cat <<END_OF_TEXT'
  cat "$@"
  echo 'END_OF_TEXT'
) > $FILE
. $FILE
Run Code Online (Sandbox Code Playgroud)

上面的示例允许$FOO在命令行上命名的文件中替换变量.我相信它可以改进,但到目前为止这对我有用.

感谢他们以前的想法的答案!

  • 0表示正常退出而不是信号. (2认同)

小智 8

如果你想要它在一行(我不是一个bash专家所以可能有一些警告,但它适用于我尝试过的所有地方):

当test.txt包含时

${line1}
${line2}
Run Code Online (Sandbox Code Playgroud)

然后:

>line1=fark
>line2=fork
>value=$(eval "echo \"$(cat test.txt)\"")
>echo "$value"
line1 says fark
line2 says fork
Run Code Online (Sandbox Code Playgroud)

显然,如果你只想打印它,你可以拿出额外的value=$()echo "$value".

  • 例如,如果 `test.txt` 包含 `"; touch /etc/your_system_is_pwned; echo "`,您将看到不好的事情发生。 (2认同)