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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 23:15:07  来源:igfitidea点击:

How to expand shell variables in a text file?

bashshellunixsolarisksh

提问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.mshand 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.mshas 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 gettextfirst: brew install gettext

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

see: Forcing bash to expand variables in a string loaded from a file

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

回答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 $FOOto 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
....