Lookaround assertions check for a pattern but do not return that pattern in the results. Lookaheads look forward for a pattern. Lookbehinds look back for a pattern.
Negative lookaheads check for the absence of a pattern before a specific pattern. ?! indicates a negative lookahead. The following expression matches a comma not followed by a number or space and replaces the pattern with a comma and space:
Regex( "one,two 1,234 cat,dog,duck fish, and chips, to go",
",(?!\d|\s)", ", ", GLOBALREPLACE );
"one, two 1,234 cat, dog, duck fish, and chips, to go"
Positive lookaheads check for the presence of a pattern before a specific pattern. ?= indicates a positive lookahead. The following expression has the same result as the preceding negative lookahead but matches a comma followed by any lowercase character:
Regex( "one,two 1,234 cat,dog,duck fish, and chips, to go",
",(?=[a-z])", ", ",GLOBALREPLACE );
"one, two 1,234 cat, dog, duck fish, and chips, to go"
data = "name=bill salary=$5 ssn=123-45-6789 age=13,name=mary salary=$6 ssn=987-65-4321 age=14";
redacted = Regex(data, "(?<=(ssn=)|(salary=))[$\d-]*", "###", GLOBALREPLACE);
"name=bill salary=### ssn=### age=13,name=mary salary=### ssn=### age=14"
Here is another way to get the same result using a backreference substitution. ((ssn=)|(salary=)) is the capturing group. "\1" is the backreference to that group.
data = "name=bill salary=$5 ssn=123-45-6789 age=13,name=mary salary=$6 ssn=987-65-4321 age=14";
redacted = Regex(data, "((ssn=)|(salary=))[$\d-]*", "\1###", GLOBALREPLACE);
"name=bill salary=### ssn=### age=13,name=mary salary=### ssn=### age=14"