在bash中扩展字符串变量以在JSON中切换值

时间:2017-08-07 21:20:29

标签: bash

我正在尝试创建一个可以切换环境的bash函数,下面是我尝试过的。我全局安装了npm json包以内联编辑相关文件,但可能不需要。

devUrl () { 'https://some-url.com'; }
testUrl () { 'https://some-test-url.com'; }
switchEnv () { 'json -I -f config.json -e "this.url = (this.url == "$1" ? "$2" : "$1")"'; }
alias switch='switchEnv devUrl testUrl';

我错过了什么/做错了什么?

我还试图在devUrl函数的双引号内对字符串testUrlswitchEnv进行模板化,但这就是我被卡住的地方。

更新

我试过了:

devUrl='https://some-url.com'
testUrl='https://some-test-url.com'
switchEnv() { json -I -f config.json -e "this.url = (this.url == "$devUrl" ? "$testUrl" : "$devUrl")"; }

但出现以下错误:

this.url = (this.url == https://some-url.com ? https://some-test-url.com : https://some-url.com)
                             ^

SyntaxError: Unexpected token :
    at new Function (<anonymous>)
    at main (/usr/local/lib/node_modules/json/lib/json.js:1289:27)

由于某种原因,它不喜欢https之后的:

1 个答案:

答案 0 :(得分:1)

以下是一个示例实现,可以执行您正在寻找的内容;请参阅下面的注释,了解实现原因的原因。

# String assignments
devUrl='https://some-url.com'
testUrl='https://some-test-url.com'
configFile="$PWD/config.json"

# Functions
switchEnv() {
  local tempfile
  tempfile=$(mktemp "$configFile.XXXXXX")
  if jq --arg a "$1" \
        --arg b "$2" \
        'if .url == $a then .url=$b else .url=$a end' <"$configFile" >"$tempfile"; then
    mv -- "$tempfile" "$configFile"
  else
    rm -f -- "$tempfile"
    return 1
  fi
}
switch() { switchEnv "$devUrl" "$testUrl"; }

注意:

  • 与别名不同,函数体应该是实际代码,而不是包含代码的字符串。
  • 存储数据(而不是代码)应该使用变量(如果适当的话,它们是字符串或数组)来完成。
  • 从代码中带外传递数据允许devUrltestUrl的恶意值逃脱其引用并运行任意jsonjq命令。这是明智的,在很大程度上是因为这些语言随着时间的推移变得更加强大:jq的旧版本没有不会在常时运行的操作,而现代版本的语言允许代码是表示可以用于拒绝服务攻击;未来的版本也可能会增加I / O支持,允许恶意代码拥有更多令人惊讶的行为。

现在,让我们说你将忽略关于分离数据和代码的重要性的警告(上图)。我们如何修改您当前的代码以正确运行&#34;&#34; (当处理的字符串是非恶意的时候)?

switchEnv() {
  json -I -f config.json -e 'this.url = (this.url == "'"$devUrl"'" ? "'"$testUrl"'" : "'"$devUrl"'")'; }
}