2017-09-10 4 views
1

J'ai un doc JSON qui ressemble à:Comment améliorer les performances d'un script jq lent?

{ 
    "SecurityGroups": [ 
     { 
      "GroupName": "database", 
      "GroupId": "sg-xxxxxx", 
      "VpcId": "vpc-yyyyyyy", 
      "IpPermissions": [ 
       { 
        "FromPort": 22, 
        "ToPort": 22, 
        "IpProtocol": "tcp", 
        "IpRanges": [ 
         { 
          "CidrIp": "10.200.0.0/16" 
         }, 
         { 
          "CidrIp": "10.200.30.79/32" 
         }, 
         { 
          "CidrIp": "10.200.42.0/24" 
         } 
        ], 
        "UserIdGroupPairs": [] 
       }, 
       { 
        "FromPort": 5555, 
        "ToPort": 5555, 
        "IpProtocol": "tcp", 
        "IpRanges": [ 
         { 
          "CidrIp": "10.200.0.0/16" 
         }, 
         { 
          "CidrIp": "10.200.0.155/32" 
         } 
        ], 
        "UserIdGroupPairs": [] 
       }, 
       { 
        "FromPort": 4506, 
        "ToPort": 4506, 
        "IpProtocol": "tcp", 
        "IpRanges": [ 
         { 
          "CidrIp": "10.200.0.0/16" 
         } 
        ], 
        "UserIdGroupPairs": [] 
       } 
      ] 
     } 
    ] 
} 

La sortie que je dois générer est la suivante:

sg-xxxxxx|database|22|22|tcp|10.200.0.0/16 
sg-xxxxxx|database|22|22|tcp|10.200.30.79/32 
sg-xxxxxx|database|22|22|tcp|10.200.42.0/24 
sg-xxxxxx|database|5555|5555|tcp|10.200.0.0/16 
sg-xxxxxx|database|5555|5555|tcp|10.200.0.155/32 
sg-xxxxxx|database|4506|4506|tcp|10.200.0.0/16 

Je suis en mesure d'atteindre cet objectif en utilisant l'aide JQ premier à générer un liste des GroupId, puis parcourez la liste pour filtrer les données dans jq deux fois. Voici comment je l'ai fait:

cat json.in | jq -r '.SecurityGroups[]|"\(.GroupId) \(.GroupName)"' | while read groupid groupname 
do 
     cat json.in | jq ".SecurityGroups[]|{GroupId,IpPermissions,IpPermissionsEgress}|select(.GroupId == \"$groupid\")" | jq -r '.IpPermissions[]|"\(.FromPort)|\(.ToPort)|\(.IpProtocol)|\(.IpRanges[].CidrIp)"' | sed "s/^/$groupid|$groupname|/" 
done 

Ma solution est lente et je voudrais améliorer, Tout pointeurs?

Répondre

3

Voici une approche plus efficace. Avec l'option -r, le filtre suivant

.SecurityGroups[] 
    | .GroupId as $gid 
    | .GroupName as $gname 
    | (.IpPermissions[], .IpPermissionsEgress[]?) 
    | .FromPort as $from 
    | .ToPort as $to 
    | .IpProtocol as $pro 
    | .IpRanges[] 
    | "\($gid)|\($gname)|\($from)|\($to)|\($pro)|\(.CidrIp)" 

avec les données de l'échantillon produit

sg-xxxxxx|database|22|22|tcp|10.200.0.0/16 
sg-xxxxxx|database|22|22|tcp|10.200.30.79/32 
sg-xxxxxx|database|22|22|tcp|10.200.42.0/24 
sg-xxxxxx|database|5555|5555|tcp|10.200.0.0/16 
sg-xxxxxx|database|5555|5555|tcp|10.200.0.155/32 
sg-xxxxxx|database|4506|4506|tcp|10.200.0.0/16 

Notez que ceci inclut .IpPermissionsEgress[]? parce que bien qu'il soit absent de vos données d'échantillon et utilisé dans la deuxième partie de votre script, il est néanmoins présent dans la première partie de votre exemple de script, donc je pense que vous avez peut-être l'intention de l'inclure.

+0

Ceci est probablement l'une de mes nouvelles paires de questions/réponses préférées, car elle fournit un bon exemple de la façon dont les variables 'jq' fonctionnent comme retour en arrière des références :) – chepner