【问题标题】:Why would bash variables not expand in while loop [duplicate]为什么bash变量不会在while循环中扩展[重复]
【发布时间】:2020-02-12 18:15:13
【问题描述】:

我有一个读取 json 文件的小脚本:

{
    "path": "$HOME/Projects:$HOME/Github"
}

我想读取path 的值,在冒号: 上拆分,然后读出两条路径 $HOME 展开

#!/bin/sh
path_list="$(jq -r '.path' < "$JSON_FILE" | tr ':' '\n')"
echo "$path_list" | while IFS= read -r line; do
    echo "$line"
done;

输出不是我所期望的

$HOME/Projects
$HOME/Github

然而,当我运行 echo "$HOME/Projects" 时,$HOME 参数扩展得很好。

最初,我认为我需要在变量两边加上双引号,所以我尝试了echo "\"${line}\"",它只打印了"$HOME/projects"。我很困惑。谁能帮我解释一下,或者指出一个关于 bash 参数扩展的好教程?

关于another SO question addressing similar issue。我不认为这是相同的,因为 OP 正在询问扩展从文件加载的字符串。我认为这不是我的问题的主要关注点。对这个问题的其他回答涉及使用eval,因为用户将输入他们自己的输入。其他解决方案依赖于外部包,如gettext。我相信这里应该有一个直截了当的答案。

【问题讨论】:

  • 参数扩展不递归扩展; $HOME 只是 "$line" 的结果中的文字字符串,而不是进一步扩展处理。
  • 如何在 while 循环上方的 path_list 声明中展开变量?
  • @Jeff: 其他环境变量是否可行或者只有$HOMEpath 的一部分
  • 您可以控制 JSON 文件吗?我建议将其设置为 jq 过滤器而不是 JSON,以便 jq 可以自己进行替换。
  • @Inian 任何环境变量都应该被允许,而不仅仅是$HOME

标签: bash variable-expansion


【解决方案1】:

通过添加'eval'解决:

#!/bin/sh
path_list="$(jq -r '.path' < "$JSON_FILE" | tr ':' '\n')"
echo "$path_list" | while IFS= read -r line; do
    eval echo "$line"
done;

更多信息:https://unix.stackexchange.com/questions/23111/what-is-the-eval-command-in-bash

【讨论】:

  • 如果没有其他选择,eval 应该是最后的手段。还有其他选择。
  • 为什么不建议这样解决?
  • 基本上,对于您的 JSON 文件中的 {"path": "$(rm -rf ~)/whatever"},导致运行 rm -rf ~ 通常是一件坏事。
  • 我现在明白了,谢谢你的解释!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-15
  • 2018-07-25
  • 1970-01-01
  • 2014-10-11
  • 2012-10-01
  • 1970-01-01
  • 2012-11-07
相关资源
最近更新 更多