我正在 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 的用途。在每个命令之前使用它只是一场噩梦 - 在命令中使用的变量上使用它。