考虑一个ASCII文本文件(假设它包含非shell脚本语言的代码):
Text_File.msh:
spool on to '$LOG_FILE_PATH/logfile.log';
login 'username' 'password';
....
现在,如果这是一个shell脚本,我可以将它作为$ sh Text_File.msh
运行,shell会自动扩展变量。
我想要做的是让shell扩展这些变量,然后创建一个新文件Text_File_expanded.msh
,如下所示:
Text_File_expanded.msh:
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
...但它没有按预期工作,输出文件虽然与源相同。
所以我不确定如何实现这一点。我的目标是让我更容易维护嵌入在我的非shell脚本中的目录路径。 这些脚本不能包含任何UNIX代码,因为它不是由UNIX shell编译的。
答案 0 :(得分:25)
此问题已在另一个帖子中提出,这是IMO的最佳答案:
export LOG_FILE_PATH=/expanded/path/of/the/log/file/../logfile.log
cat Text_File.msh | envsubst > Text_File_expanded.msh
如果在Mac上,请先安装gettext
:brew install gettext
请参阅: Forcing bash to expand variables in a string loaded from a file
答案 1 :(得分:9)
如果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';
答案 2 :(得分:8)
这个解决方案不优雅,但它有效。创建一个脚本调用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
然后您可以按照以下方式调用此脚本:
bash shell_expansion.sh Text_File.msh Text_File_expanded.msh
答案 3 :(得分: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
上面的示例允许在命令行上命名的文件中替换变量$FOO
。我相信它可以改进,但到目前为止这对我有用。
感谢以前的答案,他们的想法!
答案 4 :(得分:8)
如果你想要它在一行(我不是一个bash专家,所以可能有一些警告,但它适用于我尝试过的所有地方):
当test.txt包含
时${line1}
${line2}
然后:
>line1=fark
>line2=fork
>value=$(eval "echo \"$(cat test.txt)\"")
>echo "$value"
line1 says fark
line2 says fork
显然,如果您只想打印它,可以取出额外的value=$()
和echo "$value"
。
答案 5 :(得分:1)
如果要翻译的变量已知并且数量有限,您可以自己进行翻译:
sed "s/\$LOG_FILE_PATH/$LOG_FILE_PATH/g" input > output
并且假设变量本身已经知道
答案 6 :(得分:1)
此解决方案允许您在输出文件中保留相同的格式
在脚本中复制并粘贴以下行
cat $1 | while read line
do
eval $line
echo $line
eval echo $line
done | uniq | grep -v '\$'
这将读取作为参数逐行传递的文件,然后进行处理以尝试打印每一行两次: - 一次没有替代 - 一次替换变量。 然后删除重复的行 然后删除包含可见变量的行($)
答案 7 :(得分:0)
使用以下内容创建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
....
答案 8 :(得分:0)
是的 eval 应该谨慎使用,但这为我的问题提供了这个简单的方法。下面是使用文件名的示例:
eval "echo \"$(<Text_File.msh)\""
出于我自己的目的,我使用 printf 而不是 echo ,但这应该可以解决问题。谢谢abyss.7提供解决我的问题的链接。希望对您有所帮助。
答案 9 :(得分:0)
#logfiles.list:
$EAMSROOT/var/log/LinuxOSAgent.log
$EAMSROOT/var/log/PanacesServer.log
$EAMSROOT/var/log/PanacesStrutsGUI.log
#我的程序:
cat logfiles.list | while read line
do
eval Eline=$line
echo $Eline
done