Operator Scope of Action:
Operator First Added:
This operator tests whether pattern matches a whole discrete value string within the referenced list/set attribute. Unlike with string attributes matches using String.contains(), matches are always case-sensitive and cannot be overridden with $AgentCaseSensitive. The match gives a Boolean result.
Thus in default settings, List/Set.contains() is always:
- case-sensitive in an agent (unlike a String attribute $AgentCaseSensitive is ignored)
- case-sensitive in all other action code contexts
An always case-insensitive option is offered via List/Set.icontains() though it too cannot match below list item granularity.
pattern is one of:
- an action code expression (which includes just referencing a single attribute name')
- a quoted literal string (i.e. actual text). Important: do not omit the enclosing quotes. If omitted, Tinderbox will try to evaluate the string as an expression. Doing this may result in the expected result but this is actually a false positive. So, remember to enclose your literals in quotes.
The contains operator may also be used with both sets and lists, in which case it tests for set membership, i.e. matching to complete individual values rather than part of values. Thus:
is true if $MyList is "Monday;Tuesday;Friday". Other examples:
The left-hand argument may also be a literal list:
If the regular expression pattern is found the function return the match's offset+1, where offset is the distance from the start of the string to the start of the matched pattern. Formerly, .contains() returned true if the pattern was found. The '+1' modifier ensures that a match at position zero return a number higher than zero which would otherwise coerce to false. Since 1+offset is always true, no changes are required in existing documents but the function also now gives usable offset information.
Testing "does not contain"
Use a ! prefix to the query argument:
Use of parentheses after the !, around the query, can assist Tinderbox's parsing:
Testing lists values for partial matches
Used with care, there is a workaround by mimicking the way .replace() works with lists: see the section on regex. The trick is to use an on-the-fly list-to-string coercion allowing all list values to be regex-matched as if a single string. This is achieved by chaining List.format.contains. In order not to confuse the regex, the .format() join string should be a simple (ASCII) printable symbol that has no regex meaning. A hash (#) is a good example, though clearly this will not be good if the supplied list values include hash symbols! therefore you may need to alter the join symbol depending on your data.
Tinderbox stores a list of values, like ant/bee/cow/dog/eel, as a single semi-colon delimited string "
ant;bee;cow;dog;eel". So, for that list:
$MyList.format("#") returns "
It is possible to use a semi-colon join but it seems to tempt a parsing error, given that a semicolon is Tinderbox's list delimiter. The above result now means .contains() works as if doing a String.contains() test.
For the same data as above, these are effectively the same thing, albeit the first using a string literal:
In either case, .contains returns true, but would return false if 'bee' were removed. This is because the regex pattern only matches a double-e substring at the end of a value.
Until/unless Tinderbox's List.contains() directly supports substring matching within list values, the above offers a workaround.
Using .contains() to test individual value equivalence to a String
See == (equality) testing.
Dealing with inline quote characters