2013-01-21 32 views
11

考虑一个ASCII文本文件(可以说里面含有非shell脚本语言的代码):如何扩展文本文件中的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编译的。

+1

您的变量是否在单引号内,如上所示? – Guru

+0

@Guru - 目前,它在文本文件中是单引号或没有周边引号。 –

+1

相关问题:http://superuser.com/q/235738/126693 –

回答

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 
+0

谢谢@Hai Vu。我首先设置变量'$ LOG_FILE_PATH =/some/path'然后运行'$ ./shell_expansion.sh Text_File.msh Text_File_expanded.msh'(还有'$ bash shell_expansion.sh Text_File.msh Text_File_expanded.msh') - 但是Text_File_expanded.msh $ LOG_FILE_PATH条目被替换为空白空格。我可能是这样做不正确.. –

+1

我没有'出口'变量..我试过'$ export LOG_FILE_PATH =/SONE /路径/'它工作正常。谢谢! :) –

+0

超酷的想法! – anishsane

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'; 
+0

谢谢@Guru - 我试了一下,它工作正常..因为我需要避免依赖于Perl我不能应用此解决方案。我不是Perl专家,但是我们确定'\ w'将始终正确捕获shell变量名称。 –

+0

好吧我瞪了一眼,得到了我的答案 - 1. [PERL参考](http://www.troubleshooters.com/codecorn/littperl/perlreg.htm):\ w将匹配“字”字符(字母数字加“_” )。 2. [UNIX shell参考](http://www.tutorialspoint.com/unix/unix-using-variables.htm): 变量的名称只能包含字母数字字符和“_”。 –

+1

@KentPawar:你说得对。 – Guru

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 "[email protected]" 
    echo 'END_OF_TEXT' 
) > $FILE 
. $FILE 

上面的例子允许变量$FOO在命令行指定的文件来代替。我相信它可以得到改善,但这对我来说至今还是有效的。

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

+0

谢谢@PaulGear!欢迎来到StackOverflow。 +1使用“陷阱”清理临时文件。我已经提出了一些编辑,以使像我这样的新手更容易理解代码;请审查编辑并在需要时恢复它们。谢谢 –

+0

我没有得到'0'指的是哪个信号。 –

+2

0表示正常退出而非信号。 –

1

如果你想翻译是已知的,数量有限的变量,你总是可以做翻译自己:

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

而且还假设变量本身是已知的

7

如果你想让它在一行(我不是一个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"

+0

如果'test.txt'包含,例如,'; touch/etc/your_system_is_pwned; echo“'你会看到不好的事情发生。 – Wildcard

11

这个问题已经被问在另一个线程,这是最好的答案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

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的文件夹。
定义varible的价值被替换

myTestVariable1=SomeNewText 

现在打电话sed将替换可变

sed "$(eval echo $(cat sub.sed))" test.txt > test2.txt 

输出将是

$cat test2.txt 

Try to replace this SomeNewText 
bla bla 
.... 
0

该解决方案可以让你保持输出文件中格式相同

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

cat $1 | while read line 
do 
    eval $line 
    echo $line 
    eval echo $line 
done | uniq | grep -v '\$' 

这将改为由行参数行,然后处理通过尝试和打印的每一行两次文件: - 与替代一次 - 一旦没有取代 变量。 然后删除重复行 然后删除包含可见变量的行($)

相关问题