如何在bash中执行字符串变量的变量扩展?
我正在编写一个简单的bash调试工具,如何在bash中执行字符串变量的变量扩展?,bash,shell,parsing,debugging,environment-variables,Bash,Shell,Parsing,Debugging,Environment Variables,我正在编写一个简单的bash调试工具,log\u next\u line。预期的行为是定义log变量时,它读取脚本的下一行,展开其中的变量,将其写入$log指定的文件,执行命令,并将其输出捕获到同一日志 我有变量展开的问题。假设我在变量$line中有一行bash代码。如何在不执行任何外部程序和不执行管道(这很危险)的情况下扩展其中的字符串 简单的line=$(“echo$line”)根本不起作用。 当我尝试line=$(bash-c“echo$line”)时,我的运气更好,但是我需要将所有bas
log\u next\u line
。预期的行为是定义log
变量时,它读取脚本的下一行,展开其中的变量,将其写入$log
指定的文件,执行命令,并将其输出捕获到同一日志
我有变量展开的问题。假设我在变量$line
中有一行bash代码。如何在不执行任何外部程序和不执行管道(这很危险)的情况下扩展其中的字符串
简单的line=$(“echo$line”)
根本不起作用。
当我尝试line=$(bash-c“echo$line”)
时,我的运气更好,但是我需要将所有bash变量导出到生成的bash中(我不知道怎么做)。而调用外部程序似乎是一种过分的做法;此外,bash还将执行管道和外部程序,例如line=“echo$(rm-r/)”
有没有什么方法可以进行变量扩展,而不需要从头开始编写Bash解析器;-)?我只需要它在Linux下工作(准确地说,Ubuntu>=14.04)
对于完整的图片,我包括功能的原型:
function log_next_line()
{
if [ -n "$log" ]; then
file=${BASH_SOURCE[1]##*/} #Takes path to the file, from where the function is called
linenr=$((${BASH_LINENO[0]} + 1 )) #Line number
line=`sed "${linenr}q;d" $file` #Reads this line number from the source file
line=$("echo $line") #DOESN'T WORK. I want it to do a variable expansion
echo "\$ $line" >>$log #Writes the variable-expanded line to the log
$line >>$log 2>>$log #Executes the line and
exitstatus=$?
if [ "$exitstatus" -ne "0" ]; then
echo "## Exit status: $exitstatus" >>$log
fi
echo >>$log
BASH_LINENO[0]=$((BASH_LINENO[0] + 1)) #Skips executing of the next line, since we have already executed it (and captured its output)
if [ "$exitstatus" -ne "0" ]; then
exit $exitstatus
fi
fi
}
以及可以用作测试用例的简单脚本
#!/bin/bash
log=mylog.log
. ./log_next_line.sh
rm mylog.log
a=4
b=example
x=a
log_next_line
echo $x
log_next_line
echo ${!b}
log_next_line
touch ${!b}.txt > /dev/null
log_next_line
touch ${!x}.txt
log_next_line
if [ (( ${#a} - 6 )) -gt 10 ]; then echo "Too long string";fi
log_next_line
echo "\$a and \$x"|tee file.txt
单元测试: 如果
x=a
,a=“example”
,则我需要以下扩展:
echo$x
应该是echo a
李>
echo${!b}
应该是echo示例
touch${!b}.txt>/dev/null
应该是touch example.txt>/dev/null
if[(${a}-6))-gt 10];然后回显“字符串太长”;如果[1-燃气轮机10],则fi
应为;然后回显“字符串太长”;fi
echo“\$a和\$x”| tee file.txt
应该是echo“\$a和\$x”| tee file.txt”
这个问题是对的概括。这里给出的答案并不能通过我所有的测试用例。该函数可以实现为一个简单的
set-x
来打开脚本给定点的跟踪,并set+x
来关闭它
如果您确实希望将其实现为一行标志,我将通过调试陷阱查看并配置
-x
标志。我假设您熟悉-x
shell选项?它完全执行您试图实现的功能,但通常不需要修改源代码。您为什么要执行line=sed“${linenr}q;d“$file
?这看起来像是一场扩展噩梦。为什么不line=$(sed-n${linenr}p“$file”)
。它将从$file
中提取$linenr
,而不在双引号中嵌入行尾,即使它起作用,也是火车失事。