編寫可直接執行的 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??梢杂檬謨灾杏涊d的--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」一節查閱本文的示例即出自該節?!久赓M下載鏈接】jqCommand-line JSON processor項目地址: https://gitcode.com/GitHub_Trending/jq/jq創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考