Operator Scope of Action:
Operator First Added:
This operator allows simple text transformations without use of runCommand as was hitherto required; the result remains a List or Set as per the list of references supplied. Unlike in contains() type operators, some regex patterns are not supported for either argument; regex use is discussed in more detail below.
match and replacement are both one of:
- an action code expression (which includes just referencing a single attribute name')
- a quoted literal string (i.e. actual text)
List and set type attributes can use replace, though the scope of replacement is more limited than with strings. With listings, the match with and replacement of can only be for a complete list value and not part of a value.
A Replace action does not alter the original source
Using .replace() does not affect the source string unless the replacement output is used to overwrite the original source value. Thus if $MyString holds "Hello World" then:
$MyStringA = $MyString.replace(" World");
$MyString remains "Hello Word" and $MyStringA has value "Hello". The source is unchanged. But, if we set the source to the output
$MyString = $MyString.replace(" World");
Now $MyString becomes "Hello" and the original value is lost (overwritten by the new one.
Most basic regex expressions should work but string start (^) and string end ($) matches work in an unexpected way. When .replace() is run it looks at the internal string value of the Set or List.
Thus a list of values, like ant/bee/cow/dog/eel, is stored and matched as a single semi-colon delimited string "
ant;bee;cow;dog;eel". Note Tinderbox does not create a final semi-colon after the last value, but will not complain if the user adds one, e.g. via manual input. Thus the ^ regex pattern matches only before the 'a' of 'ant' and not the start of other list values. Similarly, $ matches after the 'g' of dog and not the end of other list values. It might be thought of as '^ant;bee;cow;dog;eel$' as opposed to '^ant$;^bee$;^cow$;^dog$;^eel$'.
So, in-list value boundaries still exist for regex matching but only as literal semicolons. Thus to change 'ee' to 'eet' in the above list but only for 'bee' and not 'eel':
$MyListA = $MyList.replace("ee;","eet;").replace("ee$","eet");
Note how two chained .replace() calls are needed, not one. The first is for inter-value boundaries and the second for the overall string end (had the data had a closing semi-colon the first match catches it so that scenario's still covered. To reverse the scenario and match the 'ee' at the start of a value:
$MyListA = $MyList.replace(";ee","ree;").replace("^ee","ree");
That changes 'eel' to 'reel' but leaves 'bee' unaltered.
It is possible to write back to the same attribute:
$MyList = $MyList.replace("ee;","eet;").replace("ee$","eet");
but, the former is a good idea whilst developing/testing code for this technique, only switching out latter once sure of the result.
Regex and Back-references
Regex can be used to set back-references in the match input string, as in an agent query, that can then be used in the replacement string. This is described in more detail here.
Trimming leading/trailing whitespace
$MyList = $MyList.replace("+","").replace(" +$","").replace(" *; *",";");
The ' +' means one or more space characters. The first replace finds such a sub-string immediately following the start of the whole string ^), whilst the second does the same for a sub-string immediately before the end of the string ($). The third replace finds zero or more space characters either side of a semi-colon (the per-item list delimiter). The latter also matches a normal ';' delimiter but the test save writing separate regexs for space before and after the delimiter (e.g. " +;" and "; +") so the zero-or-more test (*) is used here instead of the one-or-more (+) used for the start/end of the overall string. Thus, using the code above, a lists like these with items having undesired leading/trailing space:
" ant ; bee ; cow ; dog "
" ant ;bee ;cow ; dog"
Dealing with inline quote characters