Vaccano
Vaccano

Reputation: 82437

Optional element in "reduce inputs" clause

I am working on this excellent answer that I got from an earlier question.

Here is what I currently have:

function data {
cat <<EOF
Security:ClientId=123456
Security:ClientSecret=abcdefg
AppSettings:Environment=Dev
AnotherCustomSetting=SomethingElse
EOF
}

data | jq -nR '

def parse: capture("(?:(?<group>[^:=]*):)?(?<property>[^=]*)=(?<value>.*)");

reduce inputs as $line ({};
   ($line | parse) as $envVar
   | if .[$envVar.group] != null then .[$envVar.group][$envVar.property] = ($envVar.value) else .[$envVar.property] = ($envVar.value) end)
'

My end goal is to have a Json file like this:

{
  "Security": {
    "ClientId": "123456",
    "ClientSecret": "abcdefg"
  },
  "AppSettings": {
    "Environment": "Dev"
  },
  "AnotherCustomSetting": "SomethingElse"      
}

In my previous question I did not indicate that I would need properties at the root level (AnotherCustomSetting in this case).

To try to get root level properties working, I modified the RegEx to have an optional group, but the original answer's reduce inputs did not anticipate the group being null (and failed with a null error when it was). So I attempted to put an if statement in the reduce inputs section. Unfortunately it is failing with the following error:

jq: error (at :4): Cannot index object with null

Is it possible to do an if then else in a reduce inputs section like I am attempting? If so, how is it done?

Upvotes: 1

Views: 164

Answers (1)

peak
peak

Reputation: 116870

This should do it:

def parse: capture("(?<x>[^:=]*)(:(?<y>[^:=]*))?=(?<value>.*)");

reduce inputs as $line ({};
   ($line | parse) as $p
   | if $p.y then .[$p.x][$p.y] = $p.value
     else .[$p.x] = $p.value end )

Of course this could be further robustified...

Upvotes: 1

Related Questions