3
votes

JQ, comment compter selon les conditions?

En utilisant jq, je dois obtenir le nombre dans un tableau en fonction de deux critères: il DOIT avoir status === 'skipped' && ref.includes (version) code >

status=skipped; ref=v1.4.15; cat test.json | jq --arg REF "$ref" --arg STATUS "$status" -r '[.[] | select(.status==$STATUS) | select(.ref | startswith($REF))] | length'

Nous aimons également utiliser la variable d'environnement pour la requête:

  • status=skipped
  • ref=v1.4.15

Cela fonctionne mais sans options de variable d'environnement:

cat test.json | jq '[.[] | select(.status=="skipped") | select(.ref | startswith("v1.4.15"))] | length'

Comment est-ce possible?

Réponse:

[
  {
    "id": 15484,
    "sha": "52606c8da57984d1243f436e5d12e275db29a6e0",
    "ref": "v1.4.15",
    "status": "canceled"
  },
  {
    "id": 15483,
    "sha": "52606c8da57984d1243f436e5d12e275db29a6e0",
    "ref": "v1.4.15",
    "status": "canceled"
  },
  {
    "id": 15482,
    "sha": "1b4ccc1dc17e9b8ddb24550c5566d2be6b03465e",
    "ref": "dev",
    "status": "success"
  },
  {
    "id": 15481,
    "sha": "5b6ec939739c5a1513634f3b58bf96522917571d",
    "ref": "dev",
    "status": "failed"
  },
  {
    "id": 15480,
    "sha": "ec18d46f491a4645c68388df91fc41455b421e71",
    "ref": "dev",
    "status": "failed"
  },
  {
    "id": 15479,
    "sha": "dd83a6d6e58cc5114aed8016341ab3c5b3ebb702",
    "ref": "dev",
    "status": "failed"
  },
  {
    "id": 15478,
    "sha": "18ccaf4bc37bf65470b2c6ddaa69e5b4018354a7",
    "ref": "dev",
    "status": "success"
  },
  {
    "id": 15477,
    "sha": "f90900d733bce2be3d9ba9db25f8b51296bc6f3f",
    "ref": "dev",
    "status": "failed"
  },
  {
    "id": 15476,
    "sha": "3cf0431a161e6c9ca90e8248af7b4ec39c54bfb1",
    "ref": "dev",
    "status": "failed"
  },
  {
    "id": 15285,
    "sha": "d24b46edc75d8f7308dbef37d7b27625ef70c845",
    "ref": "dev",
    "status": "success"
  },
  {
    "id": 15265,
    "sha": "52606c8da57984d1243f436e5d12e275db29a6e0",
    "ref": "v1.4.15",
    "status": "success"
  },
  {
    "id": 15264,
    "sha": "9a15f8d4c950047f88c642abda506110b9b0bbd7",
    "ref": "v1.4.15-static",
    "status": "skipped"
  },
  {
    "id": 15263,
    "sha": "9a15f8d4c950047f88c642abda506110b9b0bbd7",
    "ref": "v1.4.15-static",
    "status": "skipped"
  },
  {
    "id": 15262,
    "sha": "76451d2401001c4c51b9800d3cdf62e4cdcc86ba",
    "ref": "v1.4.15-no-js",
    "status": "skipped"
  },
  {
    "id": 15261,
    "sha": "76451d2401001c4c51b9800d3cdf62e4cdcc86ba",
    "ref": "v1.4.15-no-js",
    "status": "skipped"
  },
  {
    "id": 15260,
    "sha": "515cd1b00062e9cbce05420036f5ecc7a898a4bd",
    "ref": "v1.4.15-cli",
    "status": "skipped"
  },
  {
    "id": 15259,
    "sha": "515cd1b00062e9cbce05420036f5ecc7a898a4bd",
    "ref": "v1.4.15-cli",
    "status": "skipped"
  },
  {
    "id": 15258,
    "sha": "b67acd3082da795f022fafc304d267d3afd6b736",
    "ref": "v1.4.15-node",
    "status": "skipped"
  },
  {
    "id": 15257,
    "sha": "b67acd3082da795f022fafc304d267d3afd6b736",
    "ref": "v1.4.15-node",
    "status": "skipped"
  },
  {
    "id": 15256,
    "sha": "4da4a788a85d82527ea568fed4f03da193842a80",
    "ref": "v1.4.15-bs-redux-saga-router-dom-intl",
    "status": "skipped"
  }
]


2 commentaires

Que signifie ref.includes (version) ? Cela ne ressemble pas à la syntaxe jq (et je pense que trois = est également une erreur)


Et par décompte voulez-vous dire le nombre d'éléments correspondants du tableau?


4 Réponses :


3
votes

Utilisez la fonction length () à la fin du filtre, après avoir placé la liste des objets dans un tableau

ref="1\.4\.15"
jq --arg status "$status" --arg ref "$ref" \
    '[.[] | select(.status == $status) | select(.ref | test($ref))]|length' json

mais pour simplement renvoyer les objets omis la logique pour obtenir la longueur

jq '[.[] | select(.status == "skipped") | select(.ref | test("1\\.4\\.15"))]'

Le test () est un moyen plus puissant de faire correspondre votre regex avec des chaînes JSON. Le startswith () ou endswith () ne peut pas faire correspondre les chaînes si elles sont au milieu.

Utilisation de variables,

jq '[.[] | select(.status == "skipped") | select(.ref | test("1\\.4\\.15"))] | length'


2 commentaires

Je ne peux pas être en désaccord. Prenez cette rétroaction positive et la réponse acceptée.


Juste pour commenter l'utilisation des expressions régulières, si vous comptez les utiliser, vous devez vous assurer que vous échappez les caractères qui doivent s'échapper. Ces périodes correspondent à tout ce qui peut inclure les mauvais éléments.



4
votes

En utilisant map (select (...) ou équivalent, vous pouvez utiliser length , mais il est généralement plus efficace d'utiliser une fonction de comptage générique, telle que:

jq --arg status "$status" --arg ref "$ref" -f program.jq test.json


1 commentaires

Cela ressemble à jq mais il ressemble aussi à sigma, il n'utilise pas de variable d'environnement.



1
votes

Je sais que jq est populaire ici, mais puis-je suggérer xidel ? Voir http://videlibri.sourceforge.net/xidel.html .
Tout comme jq , c'est un interpréteur JSON, mais en plus de JSONiq, vous pouvez également utiliser les fonctions XPath / Xquery pour faire toutes sortes de trucs sympas.

Cela listerait tous les objets avec les 2 critères: p >

status=skipped
ref=v1.4.15

xidel -s test.json -e 'count($json()[status="'$status'" and starts-with(ref,"'$ref'")])'

Pour les compter, entourez simplement la requête avec la fonction count () :

xidel -s test.json -e 'count($json()[status="skipped" and starts-with(ref,"v1.4.15")])'

Ceci renvoie 9.

Avec des variables:

xidel -s test.json -e '$json()[status="skipped" and starts-with(ref,"v1.4.15")]'


0 commentaires

0
votes

Par souci d'exhaustivité, ce serait une requête JSONiq équivalente:

let $a := [
   (: copy-paste the entire array here in plain JSON syntax --
      omitted for the sake of brevity :)
]
return count(
   for $obj in $a[]
   where $obj.status eq "skipped"
         and
         matches($obj.ref, "ˆv")
   return $obj
)


0 commentaires