ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

如何用 shebang 技巧(exec jq --args)编写可直接执行的 jq 脚本

如何用 shebang 技巧(exec jq --args)编写可直接执行的 jq 脚本 如何用 shebang 技巧exec jq --args编写可直接执行的 jq 脚本【免费下载链接】jqCommand-line JSON processor项目地址: https://gitcode.com/GitHub_Trending/jq/jq如果你把 jq 程序放在一个文件里平时只能这样调用它jq -n -f total.jq 1 2这种写法有两个问题参数要用--arg、--args等选项手工传递而且调用者必须知道这是一段 jq 代码。jq 官方手册的「Comments」一节给出了一个技巧利用 jq 注释和 shell 注释对同一行代码的「不同理解」在脚本里藏一行exec jq --args ...让文件既能被sh当作启动器执行又能被jq当作普通程序文件求值。完成之后你可以像调用任何命令行小工具一样直接运行./total 1 2而不用每次都敲jq前缀。前提只有一个系统已安装 jq。可以用手册中记载的--version选项确认——它会输出 jq 版本并以 0 退出jq --version技巧原理同一行代码两种解释jq 支持用#写注释#不在字符串内之后的内容直到行尾都被忽略。手册特别指出如果行尾前面有奇数个反斜杠\下一行也会被当作注释的一部分而忽略。这就是技巧的核心对 jq 来说行尾带\的#注释会把下一行也吞掉所以exec那一行对 jq 只是注释求值时被忽略对sh来说行尾的反斜杠不会延续注释所以exec那一行是真正执行的 shell 语句。sh执行到exec jq --args -MRnf -- $0 $时会用 jq 解释器替换掉自身进程以-M -R -n -f --args选项启动 jq求值当前文件$0并把传给脚本的其余参数$原样交给 jq。手册给出的展开过程是当脚本以total 1 2被调用时实际执行的是/bin/sh -- /path/to/total 1 2随后sh运行exec jq --args -MRnf -- /path/to/total 1 2。涉及的相关选项含义均出自手册「Options」一节选项作用--args--args之后的剩余参数作为位置字符串参数传入jq 程序中以$ARGS.positional[]访问-f/--from-file从文件读取过滤器此时过滤器参数被解释为文件名而不是程序源码-n/--null-input不读取任何输入过滤器以null为输入运行一次-R/--raw-input不把输入解析为 JSON每行文本作为一个字符串传给过滤器-M/--monochrome-output关闭彩色输出--终止选项解析之后的参数不再被当作选项因为--args传进来的是字符串jq 程序内部需要用tonumber自行完成数值转换——这也是下面示例中出现try tonumber catch false的原因。编写脚本手册给出的 total 示例下面这段脚本是手册中的完整示例它是一个求和工具接收若干数字参数没有参数时则从标准输入逐行读取输出它们的总和。请把它原样保存为一个文件例如total不需要.jq后缀因为它是通过-f作为顶层程序文件传入 jq 的#!/bin/sh -- # total - Output the sum of the given arguments (or stdin) # usage: total [numbers...] # \ exec jq --args -MRnf -- $0 $ $ARGS.positional | reduce ( if . [] then inputs else .[] end | . as $dot | try tonumber catch false | if not or isnan then json total: Invalid number \($dot).\n | halt_error(1) end ) as $n (0; . $n)脚本分两部分看shell 头部前 5 行第 1 行#!/bin/sh --指定由/bin/sh启动--保证后面的脚本路径不会被sh误解析为选项第 2、3 行是说明性注释对 sh 和 jq 都是注释第 4 行# \以反斜杠结尾把第 5 行的exec语句在 jq 视角下「藏」成了注释但对sh可见。jq 程序第 5 行之后$ARGS.positional是位置参数数组数组为空时改用inputs从标准输入逐行读入-R下每行是一个字符串每个值经tonumber转换不是合法数字not为false或isnan时输出 JSON 格式的错误消息并调用halt_error(1)以退出码 1 终止。赋予执行权限并运行要「直接执行」这个文件还需要给它加上可执行权限。以下命令只影响这一个文件chmod x total然后按普通命令行工具的方式调用./total 1 2手册示例注释写明该脚本的用途是「Output the sum of the given arguments (or stdin)」因此这次调用应输出 1 与 2 的和即3。验证方式正常路径运行./total 1 2若输出3说明 shebang 展开、--args参数传递和求和逻辑都工作正常。等价命令对照根据前面对展开过程的说明脚本调用最终等价于直接运行jq --args -MRnf total 1 2两条命令的输出应当一致可以用它来隔离问题——如果直接命令能跑通而./total不行问题出在 shebang 头部文件权限、exec行是否被意外改动。错误路径传入非数字参数例如./total 1 abc。示例程序会输出total: Invalid number abc.形式的 JSON 错误消息json生成、经halt_error(1)打印到 stderr 并终止。手册对halt_error(exit_code)的说明是以给定的退出码此处为 1默认值是 5停止程序。可用 shell 的$?确认退出码./total 1 abc echo $? # 期望输出 1限制与注意点这个技巧只能「藏住」exec这一行反斜杠行延续只能把紧邻的下一行并入注释因此整个 jq 程序必须从exec行的下一行开始且前面不能出现任何对 jq 非法而对 sh 又必须执行的语句。第 1 行必须是#!/bin/sh --形式由/bin/sh启动依赖sh中反斜杠不延续注释的行为把它改成直接指向jq的路径会让exec行被 jq 当作注释忽略脚本就不会工作了。--args传进来的是字符串参数程序必须自己处理类型转换与非法值这一点由示例中的try tonumber catch false分支负责改写脚本时不要删掉。完整的注释规则包括奇数/偶数个反斜杠对行延续的影响可以在 jq 官方手册 的「Comments」一节查阅本文的示例即出自该节。【免费下载链接】jqCommand-line JSON processor项目地址: https://gitcode.com/GitHub_Trending/jq/jq创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表