diff options
author | Nicolas Williams <nico@cryptonector.com> | 2015-05-18 23:02:11 -0500 |
---|---|---|
committer | Nicolas Williams <nico@cryptonector.com> | 2015-05-18 23:02:11 -0500 |
commit | cbdaeb4062cf97de2479f9c825e19088be603e88 (patch) | |
tree | 6039ed724e0a3026b6a653b7a8d31aef2a9b17b2 | |
parent | cf1306f469d0efb178f567f0b43e9af0435593ca (diff) |
Fix gsub, add gsub/3 (fix #782)
-rw-r--r-- | builtin.c | 43 | ||||
-rw-r--r-- | docs/content/3.manual/manual.yml | 2 | ||||
-rw-r--r-- | tests/all.test | 4 |
3 files changed, 31 insertions, 18 deletions
@@ -1354,24 +1354,33 @@ static const char* const jq_builtins[] = { " | $in[0:$r.offset] + s + $in[$r.offset+$r.length:]" " end ;", // + // If s contains capture variables, then create a capture object and pipe it to s + "def sub($re; s; flags):" + " def subg: explode | select(. != 103) | implode;" + // # "fla" should be flags with all occurrences of g removed; gs should be non-nil if flags has a g + " def sub1(fla; gs):" + " def mysub:" + " . as $in" + " | [match($re; fla)]" + " | if length == 0 then $in" + " else .[0] as $edit" + " | ($edit | .offset + .length) as $len" + // # create the "capture" object: + " | reduce ( $edit | .captures | .[] | select(.name != null) | { (.name) : .string } ) as $pair" + " ({}; . + $pair)" + " | $in[0:$edit.offset]" + " + s" + " + ($in[$len:] | if gs then mysub else . end)" + " end ;" + " mysub ;" + " (flags | index(\"g\")) as $gs" + " | (flags | if $gs then subg else . end) as $fla" + " | sub1($fla; $gs);", + // + "def sub($re; s): sub($re; s; \"\");", // repeated substitution of re (which may contain named captures) - "def gsub($re; s; flags):" - // # _stredit(edits;s) - s is the \"to\" string, which might contain capture variables, - // # so if an edit contains captures, then create the capture object and pipe it to s - " def _stredit(edits; s):" - " if (edits|length) == 0 then ." - " else . as $in" - " | (edits|length -1) as $l" - " | (edits[$l]) as $edit" - // # create the \"capture\" object: - " | ($edit | reduce ( $edit | .captures | .[] | select(.name != null) | { (.name) : .string } ) as $pair" - " ({}; . + $pair) )" - " | if . == {} then $in | .[0:$edit.offset]+s+.[$edit.offset+$edit.length:] | _stredit(edits[0:$l]; s)" - " else (if $l == 0 then \"\" else ($in | _stredit(edits[0:$l]; s)) end) + (. | s)" - " end" - " end ;" - " [match($re; flags + \"g\")] as $edits | _stredit($edits; s) ;", - "def gsub($re; s): gsub($re; s; \"\");", + "def gsub($re; s; flags): sub($re; s; flags + \"g\");", + "def gsub($re; s): sub($re; s; \"g\");", //####################################################################### // range/3, with a `by` expression argument diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml index 48d3de19..78967066 100644 --- a/docs/content/3.manual/manual.yml +++ b/docs/content/3.manual/manual.yml @@ -2045,7 +2045,7 @@ sections: output: '"ZabcZabc"' - - title: "`gsub(regex; string)`" + - title: "`gsub(regex; string)`, `gsub(regex; string; flags)`" body: | `gsub` is like `sub` but all the non-overlapping occurrences of the regex are diff --git a/tests/all.test b/tests/all.test index 075e8471..106afaa4 100644 --- a/tests/all.test +++ b/tests/all.test @@ -892,6 +892,10 @@ sub("^(?<head>.)"; "Head=\(.head) Tail=") ["a,b, c, d, e,f",", a,b, c, d, e,f, "] ["a,b:c:d:e,f",":a,b:c:d:e,f:"] +gsub("(?<d>\\d)"; ":\(.d);") +"a1b2" +"a:1;b:2;" + [.[] | scan(", ")] ["a,b, c, d, e,f",", a,b, c, d, e,f, "] [", ",", ",", ",", ",", ",", ",", ",", "] |