簡體   English   中英

使用 jq 如何將多個值作為參數傳遞給函數?

[英]Using jq how to pass multiple values as arguments to a function?

我有一個包含內容的 json 文件 test.json:

[
{
  "name": "Akshay",
  "id": "234"
},
{
  "name": "Amit",
  "id": "28"
}
]

我有一個包含內容的 shell 腳本:

#!/bin/bash
function display
{
  echo "name is $1 and id is $2"
}

cat test.json | jq '.[].name,.[].id' | while read line; do display $line; done

我希望單個項目的名稱和 ID 作為參數一起傳遞給函數顯示,但輸出是這樣的:

name is "Akshay" and id is 
name is "Amit" and id is   
name is "234" and id is 
name is "28" and id is 

實現代碼的正確方法應該是什么? PS:我特別想使用 jq 所以請根據 jq 來回答

兩個主要問題,以及一些對您當前的示例用例可能無關緊要但在處理來自不受信任來源的真實世界數據時可能很重要的其他項目:

  • 您當前的代碼在寫入任何id之前遍歷所有name
  • 您當前的代碼使用換行符分隔符,但沒有努力將多行讀入每個while循環迭代中。
  • 您的代碼使用換行符,但換行符可以出現在字符串中; 因此,這限制了輸入域。
  • 當您通過管道進入while循環時,該循環將在子 shell 中運行; 當管道退出時,子外殼也會退出,因此循環設置的任何變量都將丟失。
  • 與讓jq直接從test.json讀取相比,啟動/bin/cat的副本並讓jq從其輸出讀取管道是愚蠢且低效的。

我們可以解決所有這些問題:

  • 要成對編寫name s 和id s,您需要更像jq '.[] | (.name, .id)'東西jq '.[] | (.name, .id)' jq '.[] | (.name, .id)'
  • 要讀取循環的每個元素的名稱和 ID,您需要while IFS= read -r name && IFS= read -r id; do ... while IFS= read -r name && IFS= read -r id; do ...迭代這些對。
  • 要從換行符切換到 NUL(NUL 是唯一不能存在於 C 字符串或 bash 字符串中的字符),您需要將-j參數用於jq ,然后添加顯式"\"正在編寫的內容的元素。 要在 bash 端讀取此 NUL 分隔的內容,您需要將-d ''參數添加到每個read
  • 要將while read循環移出子外殼,我們可以使用進程替換,如BashFAQ #24 中所述
  • 要讓jq直接從test.json讀取,請使用<test.json讓 shell 將文件直接連接到 jq 的標准輸入,或者在 jq 的命令行上傳遞文件名。

以對包含 JSON 編碼的 NUL 的輸入數據穩健的方式執行上述所有操作將如下所示:

#!/bin/bash
display() {
  echo "name is $1 and id is $2"
}

cat >test.json <<'EOF'
[
  { "name": "Akshay", "id": "234" },
  { "name": "Amit", "id": "28" }
]
EOF

while IFS= read -r -d '' name && IFS= read -r -d '' id; do
  display "$name" "$id"
done < <(jq -j '
  def stripnuls: sub("\u0000"; "<NUL>");
  .[] | ((.name | stripnuls), "\u0000", (.id | stripnuls), "\u0000")
' <test.json)

您可以在https://replit.com/@CharlesDuffy2/BelovedForestgreenUnits#main.sh 上看到以上運行

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM