Возможно ли иметь динамический селектор в jq, используя переменные оболочки? - PullRequest
0 голосов
/ 02 апреля 2019

Мне любопытно, можно ли иметь переменную оболочки, такую ​​как:

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

и использовать эту переменную в выборе jq, например:

jq '${SEARCH}' input.json

Для справки/ тестирование может быть использовано следующее JSON кан:

[
  {
    "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 ]

1 голос
/ 02 апреля 2019

1.Ваш пример JSON недопустим, а именно 0983012 - в спецификации JSON числовые значения не могут начинаться с 0 (ну, кроме самого нуля).Вы можете использовать https://jsoncompare.com/#!/simple/ для проверки вашего JSON (jq допускает такие числа, но это отклонение от спецификации)

2.Вопрос не связан с jq, это вопрос интерполяции.Сначала вам нужно правильно определить строку, например, так:

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

, затем вы можете повторно использовать ее с помощью jq:

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 $ 

3.Кроме того, позвольте мне показать вам альтернативный подход с использованием jtc утилита unix:

bash $ SEARCH="SOMETEXT"
bash $ <file.json jtc -w"<$SEARCH>R:[-3]"
{
   "id": 729384872903,
   "notes": [
      {
         "body": "Some more more normal text [SOMETEXT]",
         "id": 983012
      },
      {
         "body": "Some more more more normal text",
         "id": 89023432
      }
   ]
}
bash $ 
1 голос
/ 02 апреля 2019

При существующем подходе определите определение фильтра в одинарных кавычках, чтобы сохранить значение литерал и не терять кавычки или не вызывать ненужное расширение переменной оболочкой. Например, враг "$var" расширяется до значения, хранящегося в заполнителе var, но '$var' сохраняется в виде простой строки.

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

Помните, что вам нужно всегда избегать двойных кавычек, вложенных друг в друга, чтобы сохранить их. Вы намного лучше используете массив и используете цитируемое расширение типа array[*], чтобы создать строку из одного слова для использования в качестве фильтра. Любые другие способы использования переменной оболочки, вероятно, будут включать разделение слов / удаление кавычек, выполняемое оболочкой, прежде чем даже передать команду jq.

При расширении массива кавычки сохраняются, и единственное, что вам нужно убедиться, это , а не для изменения значения разделителя поля ввода IFS по умолчанию.

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