Q:

jq- reference current position in loop

I have a log file called log.json that's formatted like this:  
{"msg": "Service starting up!"}  
{"msg": "Running a job!"}
{"msg": "Error detected!"}

And another file called messages.json, which looks like this:
{"msg": "Service starting up!", "out": "The service has started"}
{"msg": "Error detected!", "out": "Uh oh, there was an error!"}
{"msg": "Service stopped", "out": "The service has stopped"}

I'm trying to write a function using jq that reads in both files, and whenever it finds a msg in log.json that matches a msg in messages.json, print the value of out in the corresponding line in messages.json. So, in this case, I'm hoping to get this as output:
"The service has started"
"Uh oh, there was an error!"

The closest that I've been able to get so far is the following:
jq --argfile a log.json --argfile b messages.json -n 'if ($a[].msg == $b[].msg) then $b[].out else empty end'

This successfully performs all of the comparisons that I'm hoping to make. However, rather than printing the specific out that I'm looking for, it instead prints every out whenever the if statement returns true (which makes sense. $b[].out was never redefined, and asks for each of them). So, this statement outputs:
"The service has started"
"Uh oh, there was an error!"
"The service has stopped"
"The service has started"
"Uh oh, there was an error!"
"The service has stopped"

So at this point, I need some way to ask for $b[current_index].out, and just print that. Is there a way for me to do this (or an entirely seperate approach that I can use)?

A:

messages.json effectively defines a dictionary, so let's begin by creating a JSON dictionary which we can lookup easily. This can be done conveniently using INDEX/2 which (in case your jq does not have it) is defined as follows:
def INDEX(stream; idx_expr):
  reduce stream as $row ({};
    .[$row|idx_expr|
      if type != "string" then tojson
      else .
      end] |= $row);

A first-cut solution is now straightforward:
INDEX($messages[]; .msg) as $dict
| inputs
| $dict[.msg]
| .out 

Assuming this is in program.jq, an appropriate invocation would be as follows (note especially the -n option):
jq -n --slurpfile messages messages.json -f program.jq log.json

The above will print null if the .msg in the log file is not in the dictionary. To filter out these nulls, you could (for example) add select(.) to the pipeline.
Another possibility would be to use the original .msg, as in this variation:
INDEX($messages[]; .msg) as $dict
| inputs
| . as $in
| $dict[.msg]
| .out // $in.msg

