简体   繁体   中英

How to force bash to do variable expansion on a string?

I have read a line of bash code from the file, and I want to send it to log. To make it more useful, I'd like to send the variable-expanded version of the line.

I want to expand only shell variables. I don't want the pipes to be interpreted, nor I don't want to spawn any side processes, like when expanding a line with $( rm -r /) .

I know that variable expansion is very deeply woven into the bash. I hope there is a way to perform just expansion, without any side effects, that would come from pipes, external programs and - perhaps - here-documents.

Maybe there is something like eval ?

#!/bin/bash
linenr=42
line=`sed "${linenr}q;d" my-other-script.sh`
shell-expand $line >>mylog.log

I want a way to expand only the shell variables. if x=a , a="example" then I want the following expansions:

echo $x should be echo a .

echo ${a} should be echo example

touch ${!x}.txt should be touch example.txt

if [ (( ${#a} - 6 )) -gt 10 ]; then echo "Too long string" if [ (( ${#a} - 6 )) -gt 10 ]; then echo "Too long string" should be if [ 1 -gt 10 ]; then echo "Too long string" if [ 1 -gt 10 ]; then echo "Too long string"

echo "\\$a and \\$x">/dev/null should be echo "\\$a and \\$x>dev/null"

For those arriving five years later, and, although it is not the best answer to the OP's problem , an answer to the question is as follows. Bash can do indirect parameter expansion:

some_param=a
a=b
echo ${!some_param}
echo $BASH_VERSION
# 5.0.18(1)-release

You are absolutely right, it is very dangerous to use the bash. In fact your command suffers from your problem.

Let us discuss your script in detail:

#!/bin/bash
line=`sed "${42}q;d" my-other-script.sh`
shell-expand $line >>mylog.log

The sed may produce many lines of output, so it is misleading to use the name line .

Then you did not quote $line, this may have obscure effects:

$ x='| grep x'
$ ls -l $x
ls: cannot access |: No such file or directory
ls: cannot access grep: No such file or directory
-rw-rw-r-- 1 foo bar 34493 Nov 19 18:51 x
$

In this case the pipe is not executed, but passed to the program ls. If you have untrusted input, it is very hard to program a robust shell script.

Using eval is evil - I would never suggest using it, especially for such a purpose!

An alternative way would be in perl, iterate over the $ENV array and replace all env keys by the env values. This way you have more control over the things, which may happen.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM