You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

jq模板报错:<顶层>未定义,需更新samples列表变量值

解决jq模板变量未定义的报错问题

嘿,我帮你捋捋这个jq error: is not defined at <top-level>的问题——本质是你写的$uptime这类变量,jq压根没把它们当成你要填充的占位符,而是当成了它自己的内置变量,但这些变量你又没定义,所以就报错啦。下面给你几个实用的解决办法:

方法1:用命令行参数传递变量(最推荐)

如果你的变量是字符串或者数字这类简单类型,直接用jq的--arg(字符串)或--argjson(JSON类型,比如数字、布尔值)参数传值就好。

首先把你的模板文件(比如叫template.jq)保持原来的结构不变,变量还是用$xxx的形式:

{ 
  "test": "abc", 
  "p": "1", 
  "v": "1.0.0", 
  "samples": [ 
    { 
      "uptime": $uptime, 
      "curr_connections": $curr_connections,
      "listen_disabled_num": $listen_disabled_num,
      "conn_yields": $conn_yields,
      "cmd_get": $cmd_get,
      "cmd_set": $cmd_set,
      "bytes_read": $bytes_read,
      "bytes_written": $bytes_written,
      "get_hits": $get_hits,
      "rejected_connections": $rejected_connections,
      "limit_maxbytes": $limit_maxbytes,
      "cmd_flush": $cmd_flush
    } 
  ] 
}

然后执行命令的时候,把每个变量的值通过参数传进去:

jq --arg uptime "86400" \
   --argjson curr_connections 150 \
   --arg listen_disabled_num "0" \
   --arg conn_yields "20" \
   --arg cmd_get "1000" \
   --arg cmd_set "300" \
   --arg bytes_read "102400" \
   --arg bytes_written "204800" \
   --arg get_hits "900" \
   --arg rejected_connections "0" \
   --argjson limit_maxbytes 1073741824 \
   --arg cmd_flush "1" \
   -f template.jq /dev/null

这里加/dev/null是因为jq需要一个输入源,如果你没有其他JSON数据要处理,用空设备就行。

方法2:在jq脚本里提前定义变量

如果你不想每次都敲一堆命令行参数,可以把变量直接定义在jq脚本里,比如修改你的模板文件成这样:

# 先定义所有需要的变量
def uptime: "86400";
def curr_connections: 150;
def listen_disabled_num: "0";
def conn_yields: "20";
def cmd_get: "1000";
def cmd_set: "300";
def bytes_read: "102400";
def bytes_written: "204800";
def get_hits: "900";
def rejected_connections: "0";
def limit_maxbytes: 1073741824;
def cmd_flush: "1";

# 输出最终的JSON结构
{ 
  "test": "abc", 
  "p": "1", 
  "v": "1.0.0", 
  "samples": [ 
    { 
      "uptime": uptime, 
      "curr_connections": curr_connections,
      "listen_disabled_num": listen_disabled_num,
      "conn_yields": conn_yields,
      "cmd_get": cmd_get,
      "cmd_set": cmd_set,
      "bytes_read": bytes_read,
      "bytes_written": bytes_written,
      "get_hits": get_hits,
      "rejected_connections": rejected_connections,
      "limit_maxbytes": limit_maxbytes,
      "cmd_flush": cmd_flush
    } 
  ] 
}

然后直接执行:

jq -f template.jq

这样jq就能识别你定义的变量,顺利生成JSON啦。

方法3:用占位符替换(适合非jq原生场景)

如果你只是把这个JSON当作文本模板,不想用jq的变量系统,可以把$uptime改成{{uptime}}这类占位符,然后用sed或者其他工具替换。比如模板文件template.json

{ 
  "test": "abc", 
  "p": "1", 
  "v": "1.0.0", 
  "samples": [ 
    { 
      "uptime": "{{uptime}}", 
      "curr_connections": "{{curr_connections}}",
      "listen_disabled_num": "{{listen_disabled_num}}",
      "conn_yields": "{{conn_yields}}",
      "cmd_get": "{{cmd_get}}",
      "cmd_set": "{{cmd_set}}",
      "bytes_read": "{{bytes_read}}",
      "bytes_written": "{{bytes_written}}",
      "get_hits": "{{get_hits}}",
      "rejected_connections": "{{rejected_connections}}",
      "limit_maxbytes": "{{limit_maxbytes}}",
      "cmd_flush": "{{cmd_flush}}"
    } 
  ] 
}

然后用sed替换:

sed -e "s/{{uptime}}/86400/" \
    -e "s/{{curr_connections}}/150/" \
    -e "s/{{listen_disabled_num}}/0/" \
    -e "s/{{conn_yields}}/20/" \
    -e "s/{{cmd_get}}/1000/" \
    -e "s/{{cmd_set}}/300/" \
    -e "s/{{bytes_read}}/102400/" \
    -e "s/{{bytes_written}}/204800/" \
    -e "s/{{get_hits}}/900/" \
    -e "s/{{rejected_connections}}/0/" \
    -e "s/{{limit_maxbytes}}/1073741824/" \
    -e "s/{{cmd_flush}}/1/" \
    template.json

这种方式不需要依赖jq的语法,适合简单的批量替换场景。

最后提醒下:如果你的变量名和jq的内置函数重名,保险起见可以给变量加个前缀,比如$my_uptime,避免冲突哦。

内容的提问来源于stack exchange,提问作者nobrac

火山引擎 最新活动