变量未在另一个变量 bash 中扩展

变量未在另一个变量 bash 中扩展

我正在 bash 脚本中读取 csv 文件,如下所示:

resource='/data/bscs/'
while IFS='|'read seqid fname fpath 
do
    echo "FILENO:         $seqid"
    echo "FILENAME:       $fname"
    echo "FILE_PATH:    $fpath"                    
done < "report.csv"

我的 csv 文件具有以下值:

3|sample1.txt|$资源/操作/

我希望 $resource 在 $fname 内部扩展。相反,我得到这个输出:

FILENO:         3
FILENAME:       sample1.txt
SOURCE PATH:    $resource/operation

我已经尝试过以下方法:

"${fpath}" $(echo $fpath)

我怎样才能实现这个目标?

答案1

您可以使用eval,但是下一个维护者会咒骂你的名字。您是否尝试过在使用解析的数据时仅附加变量,或者在使用时扩展变量创造数据?

如果文件是这样创建的,难道你不能使用一些[编辑]技术来说服创建者改变他们的邪恶方式吗?

如果改变实际上是不可能的,那么你必须控制哪些变量是可能的。否则,你的脚本很容易受到各种注入攻击,例如输入3|sample1.txt|$(rm --arr --eff /)/operation/。由于你明显地控制住了这一点,您可以根据具体情况用变量的值进行一些字面替换:

IFS='/' read -a pathnames <<< "$fpath"
for pathname in "${pathnames[@]}"
do
    if [ "${pathname::1}" = '$' ]
    then
        variable_name="${pathname:1}"
        printf '%s' "${!variable_name}"
    else
        printf '%s' "$pathname"
    fi
done

使用一些额外的样板在路径名之间添加斜杠。

答案2

您还可以使用间接变量扩展

$fpath=`echo $resource/operation`
echo ${!fpath}

这将扩大fpath内资源的价值。

答案3

变量扩展只发生一次并且不是递归的。

您可以自己扩展该值:

resource=/data/bscs
fpath='$resource/operation'
echo ${fpath/'$resource'/$resource}

请注意,这比 安全得多eval,因为所有可能要替换的变量都必须在代码中列出。

答案4

我不知道为什么人们讨厌 eval。正确使用时不会造成问题。

最简单的解决方案是:

    read -p "File Path: " FILE_PATH
    FILE_PATH=$(eval echo $FILE_PATH)

编辑:(解释)简单地说,如果您知道您的数据将是操作系统路径,只需确保在使用它之前从变量扩展它即可。通过评估其中所有可能的值来做到这一点,这就是 eval 的用途。在每个命令之前使用它只是一场噩梦 - 在命令中使用的变量上使用它。

相关内容