如何在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

我正在编写一个简单的bash调试工具,
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
    ,而不在双引号中嵌入行尾,即使它起作用,也是火车失事。