Non-matched optional capture group should be null and offset -1
Fixes #3093
**Describe the bug**
I've just upgraded from JQ version 1.6 to 1.7, and noticed that the `capture` function is returning an empty string instead of `null` for an optional named group that doesn't match, but only when no other part of the regex matches.

For example, if your regex contains `(?<x>a)?`, then if the overall regular expression matches, the output from `capture` will contain a field `x` which should either have the value `"a"` if the capturing group is present, or `null` if it isn't. The problem is that there are some cases where x has the value `""` (i.e. empty string).

**To Reproduce**
Running the following code shows the issue:
`jq -cn '"a","b","c" | capture("(?<x>a)?b?")'`

The third line that is output from the command above is wrong because there is no valid case where `x` can have the value `""`.

**Expected behavior**
A capturing group that is followed by "?" should have the value `null` if the capturing group isn't present.

i.e. The expected result from running the example code above should be:
```
{"x":"a"}
{"x":null}
{"x":null}
```

However the output produced by JQ versions 1.7 and 1.7.1 are:
```
{"x":"a"}
{"x":null}
{"x":""}
```

i.e. The third line produced an `x` field with the value `""` instead of `null`.

(FYI JQ 1.6 produces `{}` as the third line of output, which is also arguably wrong, but IMHO is better than what JQ 1.7 produces.)

**Environment (please complete the following information):**

- OS and Version: Linux Ubuntu 23.10
- jq version 1.7
capture returns inconsistent results for optional named group
diff --git a/src/builtin.c b/src/builtin.c
index 717a07528a..d9553775a6 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -1006,8 +1006,13 @@ static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
         jv captures = jv_array();
         for (int i = 1; i < region->num_regs; ++i) {
           jv cap = jv_object();
-          cap = jv_object_set(cap, jv_string("offset"), jv_number(idx));
-          cap = jv_object_set(cap, jv_string("string"), jv_string(""));
+          if (region->beg[i] == -1) {
+            cap = jv_object_set(cap, jv_string("offset"), jv_number(-1));
+            cap = jv_object_set(cap, jv_string("string"), jv_null());
+          } else {
+            cap = jv_object_set(cap, jv_string("offset"), jv_number(idx));
+            cap = jv_object_set(cap, jv_string("string"), jv_string(""));
+          }
           cap = jv_object_set(cap, jv_string("length"), jv_number(0));
           cap = jv_object_set(cap, jv_string("name"), jv_null());
           captures = jv_array_append(captures, cap);

diff --git a/tests/onig.test b/tests/onig.test
index 5b6dab6a36..87aae375ea 100644
--- a/tests/onig.test
+++ b/tests/onig.test
@@ -1,7 +1,7 @@
 # match builtin
 [match("( )*"; "g")]
 "abc"
-[{"offset":0,"length":0,"string":"","captures":[{"offset":0,"string":"","length":0,"name":null}]},{"offset":1,"length":0,"string":"","captures":[{"offset":1,"string":"","length":0,"name":null}]},{"offset":2,"length":0,"string":"","captures":[{"offset":2,"string":"","length":0,"name":null}]},{"offset":3,"length":0,"string":"","captures":[{"offset":3,"string":"","length":0,"name":null}]}]
+[{"offset":0,"length":0,"string":"","captures":[{"offset":-1,"string":null,"length":0,"name":null}]},{"offset":1,"length":0,"string":"","captures":[{"offset":-1,"string":null,"length":0,"name":null}]},{"offset":2,"length":0,"string":"","captures":[{"offset":-1,"string":null,"length":0,"name":null}]},{"offset":3,"length":0,"string":"","captures":[{"offset":-1,"string":null,"length":0,"name":null}]}]
 
 [match("( )*"; "gn")]
 "abc"
@@ -37,6 +37,32 @@
 "foo bar foo foo  foo"
 [{"offset": 0, "length": 11, "string": "foo bar foo", "captures":[{"offset": 4, "length": 3, "string": "bar", "name": "bar123"}]},{"offset":12, "length": 8, "string": "foo  foo", "captures":[{"offset": -1, "length": 0, "string": null, "name": "bar123"}]}]
 
+# non-matched optional group
+"a","b","c" | capture("(?<x>a)?b?")
+null
+{"x":"a"}
+{"x":null}
+{"x":null}
+
+"a","b","c" | match("(?<x>a)?b?")
+null
+{"offset":0,"length":1,"string":"a","captures":[{"offset":0,"length":1,"string":"a","name":"x"}]}
+{"offset":0,"length":1,"string":"b","captures":[{"offset":-1,"string":null,"length":0,"name":"x"}]}
+{"offset":0,"length":0,"string":"","captures":[{"offset":-1,"string":null,"length":0,"name":"x"}]}
+
+# same as above but allow empty match for group
+"a","b","c" | capture("(?<x>a?)?b?")
+null
+{"x":"a"}
+{"x":""}
+{"x":""}
+
+"a","b","c" | match("(?<x>a?)?b?")
+null
+{"offset":0,"length":1,"string":"a","captures":[{"offset":0,"length":1,"string":"a","name":"x"}]}
+{"offset":0,"length":1,"string":"b","captures":[{"offset":0,"string":"","length":0,"name":"x"}]}
+{"offset":0,"length":0,"string":"","captures":[{"offset":0,"string":"","length":0,"name":"x"}]}
+
 #test builtin
 [test("( )*"; "gn")]
 "abc"

{"tests/onigtest": {"run": "PASS", "test": "FAIL", "fix": "PASS"}}
{"test_options": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "regset": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "callback_each_match": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tests/utf8test": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "names": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test_utf8": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "simple": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tests/base64test": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tests/uritest": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "echo": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tests/mantest": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "testc": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test_syntax": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test_back": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "bug_fix": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tests/jqtest": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "scan": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tests/shtest": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "encode": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "callout": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "listcap": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tests/optionaltest": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "user_property": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "tests/manonigtest": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test_regset": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "testcu": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "count": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "syntax": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "sql": {"run": "PASS", "test": "PASS", "fix": "PASS"}}
{"tests/onigtest": {"run": "PASS", "test": "FAIL", "fix": "PASS"}}
{"passed_count": 30, "failed_count": 0, "skipped_count": 0, "passed_tests": ["regset", "callback_each_match", "names", "test_utf8", "testc", "test_syntax", "sql", "bug_fix", "scan", "tests/onigtest", "encode", "listcap", "tests/optionaltest", "tests/manonigtest", "test_regset", "testcu", "count", "syntax", "test_options", "tests/utf8test", "simple", "tests/base64test", "tests/uritest", "tests/mantest", "test_back", "tests/jqtest", "tests/shtest", "callout", "user_property", "echo"], "failed_tests": [], "skipped_tests": []}
{"passed_count": 29, "failed_count": 1, "skipped_count": 0, "passed_tests": ["regset", "callback_each_match", "names", "test_utf8", "testc", "test_syntax", "sql", "bug_fix", "scan", "encode", "listcap", "tests/optionaltest", "tests/manonigtest", "test_regset", "testcu", "count", "syntax", "test_options", "tests/utf8test", "simple", "tests/base64test", "tests/uritest", "tests/mantest", "test_back", "tests/jqtest", "tests/shtest", "callout", "user_property", "echo"], "failed_tests": ["tests/onigtest"], "skipped_tests": []}
{"passed_count": 30, "failed_count": 0, "skipped_count": 0, "passed_tests": ["regset", "callback_each_match", "names", "test_utf8", "testc", "test_syntax", "sql", "bug_fix", "scan", "tests/onigtest", "encode", "listcap", "tests/optionaltest", "tests/manonigtest", "test_regset", "testcu", "count", "syntax", "test_options", "tests/utf8test", "simple", "tests/base64test", "tests/uritest", "tests/mantest", "test_back", "tests/jqtest", "tests/shtest", "callout", "user_property", "echo"], "failed_tests": [], "skipped_tests": []}