bash 如何在文本文件中扩展shell变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14434549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to expand shell variables in a text file?
提问by Kent Pawar
Consider a ASCII text file (lets say it contains code of a non-shell scripting language):
考虑一个 ASCII 文本文件(假设它包含非 shell 脚本语言的代码):
Text_File.msh:
文本文件.msh:
spool on to '$LOG_FILE_PATH/logfile.log';
login 'username' 'password';
....
Now if this were a shell script I could run it as $ sh Text_File.msh
and the shell would automatically expand the variables.
What I want to do is have shell expand these variables and then create a new file as Text_File_expanded.msh
as follows:
现在,如果这是一个 shell 脚本,我可以运行它,$ sh Text_File.msh
并且 shell 会自动扩展变量。我想要做的是让 shell 扩展这些变量,然后创建一个新文件Text_File_expanded.msh
,如下所示:
Text_File_expanded.msh:
Text_File_expanded.msh:
spool on to '/expanded/path/of/the/log/file/../logfile.log';
login 'username' 'password';
....
Consider:
考虑:
$ a=123
$ echo "$a"
123
So technically this should do the trick:
所以从技术上讲,这应该可以解决问题:
$ echo "`cat Text_File.msh`" > Text_File_expanded.msh
...but it doesn't work as expected and the output-file while is identical to the source.
...但它不能按预期工作,并且输出文件与源文件相同。
So I am unsure how to achieve this.. My goal is make it easier to maintain the directory paths embedded within my non-shell scripts. These scripts cannot contain any UNIX code as it is not compiled by the UNIX shell.
所以我不确定如何实现这一点。我的目标是更容易维护嵌入在我的非 shell 脚本中的目录路径。这些脚本不能包含任何 UNIX 代码,因为它不是由 UNIX shell 编译的。
采纳答案by Hai Vu
This solution is not elegant, but it works. Create a script call shell_expansion.sh:
这个解决方案并不优雅,但它有效。创建一个脚本调用 shell_expansion.sh:
echo 'cat <<END_OF_TEXT' > temp.sh
cat "" >> temp.sh
echo 'END_OF_TEXT' >> temp.sh
bash temp.sh >> ""
rm temp.sh
You can then invoke this script as followed:
然后,您可以按如下方式调用此脚本:
bash shell_expansion.sh Text_File.msh Text_File_expanded.msh
回答by Dima Lituiev
This question has been asked in another thread, and this is the best answer IMO:
这个问题已在另一个线程中提出,这是 IMO 的最佳答案:
export LOG_FILE_PATH=/expanded/path/of/the/log/file/../logfile.log
cat Text_File.msh | envsubst > Text_File_expanded.msh
if on Mac, install gettext
first: brew install gettext
如果在 Mac 上,请先安装gettext
:brew install gettext
see: Forcing bash to expand variables in a string loaded from a file
回答by Guru
If a Perl solution is ok for you:
如果 Perl 解决方案适合您:
Sample file:
示例文件:
$ cat file.sh
spool on to '$HOME/logfile.log';
login 'username' 'password';
Solution:
解决方案:
$ perl -pe 's/$(\w+)/$ENV{}/g' file.sh
spool on to '/home/user/logfile.log';
login 'username' 'password';
回答by Paul Gear
One limitation of the above answers is that they both require the variables to be exported to the environment. Here's what i came up with that would allow the variables to be local to the current shell script:
上述答案的一个限制是它们都需要将变量导出到环境中。这是我想出的允许变量是当前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
The above example allows the variable $FOO
to be substituted in the files named on the command line. I'm sure it can be improved, but this works for me so far.
上面的示例允许$FOO
在命令行上命名的文件中替换变量。我相信它可以改进,但到目前为止这对我有用。
Thanks to both previous answers for their ideas!
感谢之前的两个答案的想法!
回答by ThirteenThirtySeven
If you want it in one line (I'm not a bash expert so there may be caveats to this but it works everywhere I've tried it):
如果你想在一行中使用它(我不是 bash 专家,所以可能会有一些警告,但它在我尝试过的任何地方都有效):
when test.txt contains
当 test.txt 包含
${line1}
${line2}
then:
然后:
>line1=fark
>line2=fork
>value=$(eval "echo \"$(cat test.txt)\"")
>echo "$value"
line1 says fark
line2 says fork
Obviously if you just want to print it you can take out the extra value=$()
and echo "$value"
.
显然,如果您只想打印它,您可以去掉多余的value=$()
和echo "$value"
。
回答by tvCa
If the variables you want to translate are known and limited in number, you can always do the translation yourself:
如果您要翻译的变量已知且数量有限,您始终可以自己进行翻译:
sed "s/$LOG_FILE_PATH/$LOG_FILE_PATH/g" input > output
And also assuming the variable itself is already known
并且还假设变量本身是已知的
回答by hcii
This solution allows you to keep the same formatting in the ouput file
此解决方案允许您在输出文件中保持相同的格式
Copy and paste the following lines in your script
将以下行复制并粘贴到您的脚本中
cat | while read line
do
eval $line
echo $line
eval echo $line
done | uniq | grep -v '$'
this will read the file passed as argument line by line, and then process to try and print each line twice: - once without substitution - once with substitution of the variables. then remove the duplicate lines then remove the lines containing visible variables ($)
这将逐行读取作为参数传递的文件,然后处理尝试打印每一行两次: - 一次没有替换 - 一次替换变量。然后删除重复的行然后删除包含可见变量的行($)
回答by MarcT
Yes evalshould be used carefully, but it provided me this simple oneliner for my problem. Below is an example using your filename:
是的eval应该谨慎使用,但它为我的问题提供了这个简单的oneliner。以下是使用您的文件名的示例:
eval "echo \"$(<Text_File.msh)\""
I use printfinstead of echofor my own purposes, but that should do the trick. Thank you abyss.7 providing the link that solve my problem. Hope it helps.
我出于自己的目的使用printf而不是echo,但这应该可以解决问题。感谢 abyss.7 提供解决我问题的链接。希望能帮助到你。
回答by mcExchange
Create an ascii file test.txt with the following content:
使用以下内容创建一个 ascii 文件 test.txt:
Try to replace this ${myTestVariable1}
bla bla
....
Now create a file “sub.sed” containing variable names, eg
现在创建一个包含变量名称的文件“sub.sed”,例如
's,${myTestVariable1},'"${myTestVariable1}"',g;
s,${myTestVariable2},'"${myTestVariable2}"',g;
s,${myTestVariable3},'"${myTestVariable3}"',g;
s,${myTestVariable4},'"${myTestVariable4}"',g'
Open a terminal move to the folder containing test.txt and sub.sed.
Define the value of the varible to be replaced
打开终端移动到包含 test.txt 和 sub.sed 的文件夹。
定义要替换的变量的值
myTestVariable1=SomeNewText
Now call sed to replace that variable
现在调用 sed 来替换该变量
sed "$(eval echo $(cat sub.sed))" test.txt > test2.txt
The output will be
输出将是
$cat test2.txt
Try to replace this SomeNewText
bla bla
....