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

Bash 如何在文本文件中展开shell变量?,bash,shell,unix,solaris,ksh,Bash,Shell,Unix,Solaris,Ksh,考虑一个ASCII文本文件(假设它包含非shell脚本语言的代码): Text\u File.msh: spool on to '$LOG_FILE_PATH/logfile.log'; login 'username' 'password'; .... spool on to '/expanded/path/of/the/log/file/../logfile.log'; login 'username' 'password'; .... 现在,如果这是一个shell脚本,我可以将其作为$

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

Text\u File.msh:

spool on to '$LOG_FILE_PATH/logfile.log';
login 'username' 'password';
....
spool on to '/expanded/path/of/the/log/file/../logfile.log';
login 'username' 'password';
....
现在,如果这是一个shell脚本,我可以将其作为
$sh Text_File.msh
运行,shell将自动展开变量。 我要做的是让shell展开这些变量,然后创建一个新文件,名为
Text\u file\u expanded.msh
,如下所示:

文本文件已展开。msh:

spool on to '$LOG_FILE_PATH/logfile.log';
login 'username' 'password';
....
spool on to '/expanded/path/of/the/log/file/../logfile.log';
login 'username' 'password';
....

考虑:

$ a=123
$ echo "$a"
123
因此,从技术上讲,这应该可以做到:

$ echo "`cat Text_File.msh`" > Text_File_expanded.msh
…但它无法按预期工作,输出文件while与源文件相同


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

此解决方案并不优雅,但可以工作。创建一个脚本调用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

如果Perl解决方案适合您:

示例文件:

$ cat file.sh
spool on to '$HOME/logfile.log';
login 'username' 'password';
解决方案:

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

上述答案的一个限制是,它们都要求将变量导出到环境中。下面是我提出的允许变量在当前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
#/垃圾箱/垃圾箱
FOO=bar;
FILE=`mktemp`.#让shell创建一个临时文件
陷阱“rm-f$FILE”0 1 2 3 15;#清理临时文件
(

echo'cat如果要转换的变量已知且数量有限,则始终可以自己进行转换:

sed "s/\$LOG_FILE_PATH/$LOG_FILE_PATH/g" input > output

同时假设变量本身已经为人所知,如果您想将其放在一行中(我不是bash专家,因此可能有一些警告,但它在我尝试过的任何地方都有效):

当test.txt包含

${line1}
${line2}
然后:


显然,如果您只想打印它,您可以取出额外的
value=$()
echo“$value”

这个问题已经在另一个线程中提出,这是我的最佳答案:

export LOG_FILE_PATH=/expanded/path/of/the/log/file/../logfile.log
cat Text_File.msh | envsubst > Text_File_expanded.msh
如果在Mac上,首先安装
gettext
brew安装gettext

见:

创建包含以下内容的ascii文件test.txt:

Try to replace this ${myTestVariable1} 
bla bla
....
现在创建一个包含变量名的文件“sub.sed”,例如

's,${myTestVariable1},'"${myTestVariable1}"',g;
s,${myTestVariable2},'"${myTestVariable2}"',g;
s,${myTestVariable3},'"${myTestVariable3}"',g;
s,${myTestVariable4},'"${myTestVariable4}"',g'
打开一个终端,移动到包含test.txt和sub.sed的文件夹。
定义要替换的变量的值

myTestVariable1=SomeNewText
现在调用sed替换该变量

sed "$(eval echo $(cat sub.sed))" test.txt > test2.txt
输出将是

$cat test2.txt

Try to replace this SomeNewText 
bla bla
....

此解决方案允许您在输出文件中保持相同的格式

复制并粘贴脚本中的以下行

cat $1 | while read line
do
  eval $line
  echo $line
  eval echo $line
done | uniq | grep -v '\$'
这将逐行读取作为参数传递的文件,然后尝试打印每行两次: -一次不换人 -一次,替换变量。 然后删除重复的行 然后删除包含可见变量($)的行。

应该小心使用Yes eval,但它为我的问题提供了一个简单的单行代码。下面是使用文件名的示例:

eval "echo \"$(<Text_File.msh)\""
eval“echo\”$(#logfiles.list:

$EAMSROOT/var/log/LinuxOSAgent.log
$EAMSROOT/var/log/panaccesserver.log
$EAMSROOT/var/log/panaccesstrutsgui.log
#我的节目:

cat logfiles.list |读取行时
做
eval Eline=$line
回音$Eline
完成

您的变量是否如上图所示在单引号内?@Guru-目前,它在文本文件中是在单引号内还是根本没有引号。相关问题:谢谢@Hai Vu。我首先设置变量
$LOG\u file\u PATH=/some/PATH
,然后运行
$./shell\u expansion.sh text\u file.msh text\u expansed.msh
(还有
$bash shell_expansion.sh Text_File.msh Text_File_expansed.msh
)-但是在Text_File_expanded.msh中,$LOG_File_PATH条目被替换为空格。我可能做得不正确。.我没有导出变量。.在我尝试后,
$export LOG_File_PATH=/sone/PATH/
工作正常。谢谢!)不需要使用临时文件,只需使用
eval
-参见@ThirtenthirtySeven的答案。此外,使用临时文件的方法也有一些问题(多个
shell_expansion.sh
实例将全部写入同一个文件、权限问题、错误检查等-临时文件将产生许多潜在的复杂问题,您需要准备好处理或了解以避免这些问题)。
eval
比使用临时文件更危险。我发现
echo-e“cat Thank@Guru-我试过了,效果很好。因为我需要避免对Perl的依赖,所以无法应用此解决方案。我不是Perl专家,但我们是否确定
\w
将始终正确捕获shell变量名…?好的,我目瞪口呆,得到了我的答案-1:\w将匹配“word”字符(字母数字加“”).2.:变量名称只能包含字母数字字符和“.Hi All”-以上注释中的拼写错误:
”\
被视为未标记为代码,因此用于生成斜体文本。对不起,我尝试了你的脚本。它几乎可以正常工作。它将替换所有env变量,无论它们是否定义。我认为避免替换未定义的变量会很有用。谢谢@PaulGear!欢迎使用StackOverflow.+1用于使用
trap
清理临时文件。我建议进行一些编辑,以便像我这样的新手更容易理解代码;请检查编辑并在需要时还原它们。感谢我没有得到
0
所指的信号。0表示正常退出,而不是信号。我不确定你为什么要这样做我认为半成品在变量赋值和陷阱上是必要的,但不是echos和cats,但是注释是有用的,所以我不打算回复。谢谢Paul。关于半成品-只是在添加注释时添加了它们;不是必要的,只是习惯使然:)If
test.txt
包含,例如,
“触摸/etc/your_系统;回声”