Populate captures also for zero-width matches

Instead of just using {"captures":[]}.

sub functions are use captures for replacement expressions.
If we don't populate, captures for empty matches, the replacement
expression is run with an empty object as input instead of an object
containing the named captures with "" as value:

* before:

  $ jq -n '"123foo456bar" | gsub("[^a-z]*(?<x>[a-z]*)"; "Z\(.x)")'
  "ZfooZbarZnull"

* after:

  $ jq -n '"123foo456bar" | gsub("[^a-z]*(?<x>[a-z]*)"; "Z\(.x)")'
  "ZfooZbarZ"

---

I also removed a redundant

  result = NULL;
  if (result) {
    ...
  }
This commit is contained in:
Emanuele Torre authored and Nico Williams committed 2023-07-18 12:12:50 -05:00
1 parent bb0f898c01
commit 01dfd8b86d
2 files changed
+16 -4

No files matched your search

+11 -3
View File
@@ -931,7 +931,17 @@ static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
jv match = jv_object_set(jv_object(), jv_string("offset"), jv_number(idx));
match = jv_object_set(match, jv_string("length"), jv_number(0));
match = jv_object_set(match, jv_string("string"), jv_string(""));
match = jv_object_set(match, jv_string("captures"), jv_array());
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(""));
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);
}
onig_foreach_name(reg, f_match_name_iter, &captures);
match = jv_object_set(match, jv_string("captures"), captures);
result = jv_array_append(result, match);
// ensure '"qux" | match("(?=u)"; "g")' matches just once
start = (const UChar*)(input_string+region->end[0]+1);
@@ -1005,8 +1015,6 @@ static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
} while (global && start <= end);
onig_region_free(region,1);
region = NULL;
if (region)
onig_region_free(region,1);
onig_free(reg);
jv_free(input);
jv_free(regex);
+5 -1
View File
@@ -1,7 +1,7 @@
# match builtin
[match("( )*"; "g")]
"abc"
[{"offset":0, "length":0, "string":"", "captures":[]}, {"offset":1, "length":0, "string":"", "captures":[]}, {"offset":2, "length":0, "string":"", "captures":[]}, {"offset":3, "length":0, "string":"", "captures":[]}]
[{"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}]}]
[match("( )*"; "gn")]
"abc"
@@ -145,6 +145,10 @@ gsub("\\b(?<x>.)"; "\(.x|ascii_downcase)")
"ABC DEF"
"aBC dEF"
gsub("[^a-z]*(?<x>[a-z]*)"; "Z\(.x)")
"123foo456bar"
"ZfooZbarZ"
# utf-8
sub("(?<x>.)"; "\(.x)!")
"’"