In if tests, the Tasker app for android provides four different ways to test strings. (Some of these are also used in the Variables->Variable Search Replace command.)
(The tests with names of the form Maths:... are not included here, as they are not string tests but numeric tests.)
Which one should be used where? And what are hints for making the best use of each one?
Remember, what are described here are string tests. In a few cases some of these tests may produce mysterious results when one or both of their inputs are numbers. 1 will not match either 01 or 1.0. If you need what you're testing to be treated like numbers, use the numeric tests (those of the form Maths:...).
These tests are the fastest, and may be appropriate when performance is a top concern. To make them work though you need to specify the full string exactly. Even the case must match. So off matches off but does not match Off. And of course an invisible trailing space will also cause the strings to not match.
To use these tests reliably, make one of your coding conventions that all string values that might be tested are only one word and are all lower case, and be careful to never type in any spaces.
These tests are not usually case sensitive (although individual tests can be made case sensitive if that's what you need). The wildcard * (asterisk or star) matches any number of characters (including no characters at all), and the wildcard + (plus sign) matches one or more characters.
The metacharacter / (forward slash) separates alternatives, as it does elsewhere in Tasker [note that this is different from the | (vertical bar or logical or) metacharacter you may be used to]. Thus it is valid to code for example *this*/*that* . Note that each of the alternatives is matched against the entire string. As the simple style of string matching does not include grouping parentheses, it is not possible to specify alternatives for part of a string.
An entire test can be reversed by prefixing it with ! (exclamation point) like !*jack built*. (To test for a literal exclamation point at the very beginning of a string, start the pattern with an extra wildcard like *!*unusual#pattern* so the special handling of exclamation point at the beginning of a pattern will not be triggered.) To make the test case sensitive, include at least one upper case letter in the pattern, so *Jack built* would match This is The House that Jack built but not This is The House that Jack Built. (There does not seem to be any simple way of matching a string only if it's all lower case.) Tests with an entirely empty pattern or against an entirely empty string are somewhat baroque and should be avoided (or at least used with care).
The biggest gotcha about these tests is that they require that the entire string be matched. So This is the house that Jack built would be matched by *jack* but would not be matched by *jack because that pattern does not match the entire string.
These tests provide a simple, logical way to do string testing, and may be all you need if your programming is fairly simple. Unfortunately these tests are not exactly like anything else. And although they work just fine most of the time, you can occasionally get into a corner where you wish to do a test they simply cannot do. As this was an earlier form of string test in Tasker, you may see it more frequently in older code examples. These tests can still be used in new code if you have a preference for them. Regular Expressions though can be a more robust -and likely faster- replacement for all of these tests ...and more.
These Regular Expression tests are by default case sensitive (although any particular test can be changed). They match only the part of the string specified by the pattern; tests need not and should not attempt to match the other parts of the string too. All the egrep Regular Expression additions are supported (alternation or logical or, grouping, meta-characters are escaped only when used literally), as are pretty much all the PCRE (Perl Compatible Regular Expression) extensions (lookahead, lookbehind, change flags, unified word break, testing against strings with embedded newlines, etc.). The execution is actually handled by Java, so in an uncommon edge case Java Regular Expression semantics and syntax are usually the best guide to what's really going on under the covers.
(The results of all matches, which are commonly available after any use of most Regular Expression flavors, are not available through Tasker string testing. Capturing parentheses and the dollar variables are only meaningfully available in the Tasker Variables->Variable Search Replace instruction.)
Use these tests the opposite of how you'd use the Simple Tests. While the Simple tests are case-insensitive and must match the whole string, these Regular Expression tests default to case-sensitive and typically only match a part of the string.
The flag-changing syntax can be used to make one of these tests case-insensitive. For example This is the house that Jack built will be matched by (?i)jack built, as the pattern sets the i flag (case insensitivity). These Regular Expressions can do a lot; for example the pattern house.*built will match, as will the pattern \bbuil((?=)(der|t)\b) (which will leave the pointer in the middle of the last word of the phrase, before the lookahead).
These Regular Expressions can be very powerful; they form an entire computer language if you choose to use them that way. A complete explanation of how to use these Regular Expressions is well beyond the scope of this page. There are many Regular Expression tutorials and references on the web; there's even a book on just Regular Expressions if you really want to delve deeply (see especially the chapter on the Java flavor of Regular Expressions) ...or you can stick to using only a subset of these Regular Expressions, by specifying patterns as only the whole words you care about matching, without any flags or lookaheads or lookbehinds or other complications.
Does this variable have some value (Variables->Variable Set)? Or is it nonexistent or empty (Variables->Variable Clear)? These are not string matching tests like the others above, but rather simply string existence tests.
To test the length of a string, use the Variables->Test Variable command.
The situation of a simple true/false flag available to several different Tasks simultaneously is common. Using a global variable is a good way to do this (the variable is Global if it's name includes at least one upper-case character). Here's the pattern I recommend for implementation.
While there is no single instruction in Tasker that will report the number of occurrences of a substring, a sequence of just two instructions will do it:
First, use a Variables->Variable Set instruction to record the size of the array (which is the number of occurrences of the substring). For Name specify the variable the answer should be placed in (for example %numsubs). And for To specify %match(#).
Then do whatever you want with the number of occurrences of the substring as recorded in the variable you specified (for example %numsubs).
String search and replace is done by the Tasker instruction Variables->Variable Search Replace. That instruction is more complex than most Tasker instructions; there are a lot of fields and checkboxes, each of which modify its behavior slightly (the examples below assume the Replace Matches box is checked and none of the other boxes are checked). The actual execution is handled by the Java (before-and-after string).replaceXXX(search regular expression, replacement text) functions.
The search Regular Expression is often a simple word (or a variable containing a word). It can also include lookbehinds, lookaheads, or even flags (although these are seldom necessary as there's a checkbox corresponding to each flag). The search regular expression can even include pairs of parentheses identifying the parts to be extracted (as always the entire phrase will be replaced though, not just the part within the pair of parentheses). The replacement text is also often a simple word (or a variable containing a word).
In more complex cases the replacement text can also contain dollar signs; $1, $2, $3, ... are variables containing the extracted text, and their values are substituted like regular Tasker variables (except if there was more than one match, each instance has its own value, which is retrieved at the appropriate time). [An example of regular Tasker variable substitution: %abc becomes xyz.] $1 refers to the first pair of parentheses, $2 to the second pair of parentheses, $3 to the third pair of parentheses, and so on. Remember, $2 refers to the second pair of parentheses, which is not always the same as the second match. (Parentheses pairs and matches -although often the same- can be different.) Parentheses are for extraction only; they have nothing to do with what will be replaced. The entire matched portion of the search string will be replaced, regardless of whether or not the pattern contains one or more pairs of parentheses.
If you want a list of all the matches in the order they were in the original string (rather than the order of pairs of parentheses in the Search string), and only one match per index (rather than the possibility of a whole set), you can specify a Tasker variable in which all the matches will be recorded as an array, then separated so you can access them in the usual Tasker way.
Here are some examples, all operating on the same string
(This is the house -really the house- that Jack built)
Search and replace is very powerful; with cleverness you can do a whole lot with it. But you probably shouldn't. Even constructs parallel to the last five examples above -which illustrate just how convoluted Search&Replace can be- should probably be avoided. Others won't be able to understand your code. Even you yourself may lose track of how your code works. And the behavior of undocumented edge cases may differ in different releases.
Tasker's sensing that a notification appeared always uses simple string testing. So any field that's specified must match the entire string in the notification. Taking the Text parameter as an example, you probably wish to specify a match something like *kilroy*. If you instead code just kilroy without the wildcard asterisks (which would be correct for the regular expression style of string matching), the profile will never match, yet will not generate any error.
It is easy to increase the specificity of a match with the simple style of string matching. Just identify several words, all of which always appear in the same order. Then specify all of them in order, something like *this*house*built* for example.
The above presentation draws heavily from the Tasker pattern matching documentation.