On Thu, Oct 24, 2024 at 02:58:00AM +1100, Viktor Dukhovni via mailop wrote:

> The below works if it is not too costly to hold the entire thing in
> memory.  It can be optimised for streaming, but the "jq" script becomes
> harder to understand.
> 

The streaming version (execute as: jq --stream -nr -f script.jq
input.json) is below.  This also filters to the values prior to output,
rejecting data with embedded control characters or addresses with
something other than hex digits '.' or ':' (plausibly, but not
necessarily v4 or v6 addresses).

The sample input therefore needs more realistic addresses (no XXX).

-- 
    Viktor.

def init: { ix: -1, wip: {} };

def update($pv):
    $pv[0][0] as $ix
  | $pv[0][1:] as $p
  | $pv[1] as $v
  | if .ix != $ix or $p == []
    then .done = .wip | .wip = { addrs: [] }
    else .done = {}
    end
  | .ix = $ix
  | if ([$v, $p[-1]] | map(type)) == ["string", "string"]
    then if $p[0] == "client"
         then .wip |= setpath($p; $v)
         elif $p[0] == "ips" and $p[-2] == "active"
         then .wip.addrs += [[$p[-1], $v]]
         else .
         end
     else .
     end;

def extract:
    .done
  | select(.client.name? | type == "string" and . != "")
  | select(.client.complaint_address? | type == "string" and . != "")
  | select(.addrs | type == "array" and . != [])
  | select(.client.name | test("^[ -~]*$"))
  | select(.client.complaint_address | test("^[ -~]*$"))
  | select(.addrs | all(.[0] | test("^[a-fA-F0-9.:]*$")))
  | select(.addrs | all(.[1] | test("^[ -~]*$")))
  | ( "## Name: \(.client.name)"
    , "## Abuse: \(.client.complaint_address)"
    , ( .addrs[]
      | ( "# \(.[1])"
        , "\(.[0]) permit"
        )
      )
    , ""
    );

foreach inputs as $pathval (init; update($pathval); extract)
_______________________________________________
mailop mailing list
mailop@mailop.org
https://list.mailop.org/listinfo/mailop

Reply via email to