【问题标题】:String expansion - escaped quoted variable to value字符串扩展 - 将带引号的变量转义为值
【发布时间】:2016-06-30 14:44:08
【问题描述】:

首先,这是我正在运行的脚本来获取有问题的字符串:

# sed finds all sourced file paths from inputted file.
#
# while reads each match output from sed to $SOURCEFILE variable.
# Each should be a file path, or a variable that represents a file path.
# Any variables found should be expanded to the full path.
#
# echo and calls are used for demonstractive purposes only 
# I intend to do something else with the path once it's expanded.

PATH_SOME_SCRIPT="/path/to/bash/script"

while read -r SOURCEFILE; do
    echo "$SOURCEFILE"
    "$SOURCEFILE"
    $SOURCEFILE
done < <(cat $PATH_SOME_SCRIPT | sed -n -e "s/^\(source\|\.\|\$include\) //p")

您可能还希望使用以下内容将其作为模拟数据进行测试:

[ /path/to/bash/script ]

#!/bin/bash
source "$HOME/bash_file"
source "$GLOBAL_VAR_SCRIPT_PATH"

echo "No cow powers here"

对于 tl;dr 工作人员来说,while 循环基本上会在模拟数据上吐出以下内容:

"$HOME/bash_file"
bash: "$HOME/bash_file": no such file or directory
bash: "$HOME/bash_file": no such file or directory
"$GLOBAL_VAR_SCRIPT_PATH"
"$GLOBAL_VAR_SCRIPT_PATH": command not found
"$GLOBAL_VAR_SCRIPT_PATH": command not found

我的问题是,你能否让变量正确展开,例如打印“/home//bash_file”和“/expanded/variable/path”?我还应该声明虽然eval 有效,但我不打算使用它,因为它的potential insecurities

提示cat | sed 中使用的任何变量值都将在全局范围内可用,包括调用脚本,所以这不是因为脚本无法调用变量值。


第一个解决方案尝试

使用 anubhava 的envsubst 解决方案:

SOMEVARIABLE="/home/nick/.some_path"
while read -r SOURCEFILE; do 
    echo "$SOURCEFILE"
    envsubst <<< "$SOURCEFILE"; 
done < <(echo -e "\"\$SOMEVARIABLE\"\n\"$HOME/.another_file\"")

这会输出以下内容:

"$SOMEVARIABLE"
""
"/home/nick/.another_file"
"/home/nick/.another_file"

不幸的是,它没有扩展变量!亲爱的:(


第二个解决方案尝试

基于第一次尝试:

export SOMEVARIABLE="/home/nick/.some_path"
while read -r SOURCEFILE; do 
    echo "$SOURCEFILE"
    envsubst <<< "$SOURCEFILE"; 
done < <(echo -e "\"\$SOMEVARIABLE\"\n\"$HOME/.another_file\"")
unset SOMEVARIABLE

它可以在没有 eval 的情况下产生我们想要的结果,并且不会弄乱全局变量(反正时间太长了),哇!


还建议使用eval(尽管可能不安全)获得好的亚军,这可以在this answerhere 中找到(链接由anubhava 的扩展cmets 提供)。

【问题讨论】:

  • 请注意,如果您在此评论之前阅读此问题,我已更改第三个评论块中的两个输出错误,因为它们不正确 - 道歉!
  • 感谢您更新问题,提供所有相关详细信息和建议的链接 +1

标签: bash sed cat variable-expansion


【解决方案1】:

我的问题是,您能否让变量正确展开,例如打印"/home//bash_file""/expanded/variable/path"

是的,您可以使用envsubst program,它替换环境变量的值:

while read -r sourceFile; do
   envsubst <<< "$sourceFile"
done < <(sed -n "s/^\(source\|\.\|\$include\) //p" "$PATH_SOME_SCRIPT")

【讨论】:

  • 完美运行!感谢您的帮助
  • 它会起作用,只需在您的变量声明之前添加export 以使其可用于环境。所以让它export SOMEVARIABLE="/home/nick/.some_path"
  • 你是神!谢谢,有没有办法在不导出的情况下做到这一点?有时我只想将变量本地化为一个函数。显然export local variable= 是有效的 bash,但它在函数范围之外仍然可用。
  • Take a look here 虽然我相信即使这样也不安全。
  • 很棒的研究——我遇到过类似的解决方案。我认为为了安全起见,export VARIABLE 然后在操作完成后使用unset VARIABLE 是实现所有目标的最佳方法 - 这个问题很快就会更新。谢谢!
【解决方案2】:

我想您是在问如何在 bash 中递归扩展变量。试试

expanded=$(eval echo $SOURCEFILE)

在你的循环中。 eval 运行你给它的扩展命令。由于$SOURCEFILE 不在引号中,因此它将扩展为例如$HOME/whatever。然后eval 将扩展$HOME,然后将其传递给echoecho 将打印结果,expanded=$(...) 将打印结果放入$expanded

【讨论】:

  • 我只是避免投反对票,因为我没有指定eval!我实际上知道这种方法有效,但是eval 非常不安全,除非非常小心地使用,否则应该不惜一切代价避免作为这类脚本中的解决方案 - 不幸的是,在这个答案中它没有被足够小心地使用,被认为是安全的 IMO .请在此处进一步阅读:stackoverflow.com/questions/17529220/…
  • 请注意我已经更新了答案以反映上述评论 - 很抱歉没有尽快这样做。被评为编辑前正确的解决方案。
猜你喜欢
  • 2012-06-29
  • 2015-10-27
  • 2010-10-24
  • 1970-01-01
  • 1970-01-01
  • 2012-11-03
  • 2012-05-30
  • 2021-07-29
  • 2015-04-17
相关资源
最近更新 更多