可以使用壳变量在jq中使用动态选择器吗?

时间:2019-04-02 08:58:51

标签: json shell jq

我很好奇是否可能有像这样的shell变量:

SEARCH=".[] | select(.notes[] | select(.body|contains("[SOMETEXT]")))"

并在jq选择中使用该变量,例如:

jq '${SEARCH}' input.json

作为参考/测试,将使用以下JSON kan:

[
  {
    "id": 74892374923,
    "notes": [
      {
        "id": 8902348023,
        "body": "Some normal text"
      },
      {
        "id": 8094328420,
        "body": "Some more normal text"
      }
    ]
  },
  {
    "id": 729384872903,
    "notes": [
      {
        "id": 0983012,
        "body": "Some more more normal text [SOMETEXT]"
      },
      {
        "id": 89023432,
        "body": "Some more more more normal text"
      }
    ]
  }
]

2 个答案:

答案 0 :(得分:1)

使用您现有的方法在单引号中定义过滤器定义,以保留 literal 值,并且不丢失引号或不强制外壳进行任何不必要的变量扩展。敌人,例如"$var"扩展为占位符var中存储的值,但是'$var'作为纯字符串存储。

SEARCH='.[] | select(.notes[] | select(.body|contains("[SOMETEXT]")))'
jq "$SEARCH" json

请记住,必须始终对彼此嵌套的双引号进行转义,以保留它。使用数组会更好一些,并使用引号array[*]的引号扩展来生成单个单词字符串以用作过滤器。使用shell变量的任何其他方式都可能会涉及shell甚至在传递给jq命令之前进行的单词拆分/引用删除操作。

通过数组扩展,引号得以保留,唯一需要确保的是 not ,以将输入字段分隔符IFS的值更改为默认值。

ary=('.[]' '|' 'select(.notes[] | select(.body|contains("[SOMETEXT]")))')
jq "${ary[*]}" json

答案 1 :(得分:1)

1。您的JSON示例无效,即$user->likes->to_user_id -在JSON规范中,数字不能以0983012开头(嗯,零本身除外)。您可以使用https://jsoncompare.com/#!/simple/来验证JSON(jq允许这样的数字,但这与规范不符)

2。问题与jq无关,与cli插值有关。首先,您需要正确定义字符串,例如像这样:

0

然后您可以将其与jq重复使用:

bash $ SEARCH='.[] | select(.notes[] | select(.body|contains("[SOMETEXT]")))'

3。另外,让我向您展示使用 jtc Unix实用程序的另一种方法:

bash $ <file.json jq "$SEARCH"
{
  "id": 729384872903,
  "notes": [
    {
      "body": "Some more more normal text [SOMETEXT]",
      "id": 983012
    },
    {
      "body": "Some more more more normal text",
      "id": 89023432
    }
  ]
}
bash $