Re: Pent: I want to document Tasker Regex

1,443 views
Skip to first unread message

Pent

unread,
Mar 30, 2013, 12:11:37 PM3/30/13
to Tasker

> It just does not work as expected (vs. multiple other implementations).

All the perl-style matches I have tried have worked as expected.

>While I'm not Larry Wall, I could write a very good Regex-in-Tasker explanation for the user guide.  The Android dev >page is nice, but we (users) are not at the Java level.

I would be grateful to be able to incorporate it. Oftern newbies need
the power but lack the knowledge.

> There's just one little catch... I will need the code for said action.  I will sign something in blood to assuage any fears >that I might let it go public.

I don't know why, but it's below.

Pent

int flags = 0;

if ( caseInsensitive )
flags |= Pattern.CASE_INSENSITIVE;

if ( multiline )
flags |= Pattern.MULTILINE;

Pattern searchPattern = null;

try {
searchPattern = Pattern.compile( search, flags );
}
catch ( PatternSyntaxException e ) {
Log.w( TAG, "bad search pattern: " + search );
returnStatus = ACTION_EXECUTE_STATUS_STOP_TASK;
}

if ( returnStatus == ACTION_EXECUTE_STATUS_OK ) {

Matcher matcher =
searchPattern.matcher( varContents );

// FIND

int matchCount = 0;

while ( matcher.find() ) {

String matchingString = matcher.group();

matchCount++;

if ( wantStoreFlag )
Variables.pushArray( this,
storeInVarName, Integer.MAX_VALUE, matchingString, false, taskVars );

if ( onlyFirstFlag )
break;
}

// REPLACE

if ( wantReplaceFlag && ( matchCount > 0 ) ) {

matcher.reset();

String newval = onlyFirstFlag ?
matcher.replaceFirst( replace ) : matcher.replaceAll( replace );

Variables.storeValue( this, varName, newval,
true, taskVars );
}
}

Pent

unread,
Apr 1, 2013, 7:00:20 AM4/1/13
to Tasker
> Hi, looking at the code it seems to me that captured groups are not handled: groupCount/group(i) functions do not >appear. If that is correct it would definitely be a huge improvement if that becomes somehow available in coming >releases. If that is not correct, how do I access a captured group

find() increments the group count.

Pent

Mersenne Twister

unread,
Apr 1, 2013, 8:03:13 AM4/1/13
to tas...@googlegroups.com
Thanks. Then I do not understand why the basic example in the developper doc ( http://developer.android.com/reference/java/util/regex/Pattern.html) does not work as expected.
string abc
pattern a((b)c)
the result should be a 3 items array(abc,bc,b), right?
But in Tasker it gives a single item array (abc).
It seems that Tasker loops on the whole matches (abcabc and the same pattern gives array (abc, abc)) rather than on the captured groups. Is it the intended behaviour?

Kurt Anderson

unread,
Apr 1, 2013, 9:59:12 PM4/1/13
to tas...@googlegroups.com
As it turns out, the code was critical to understanding why it doesn't behave as I expected... and some other tidbits.

find() finds the next match of the entire regex from the Search field.

If you have the string "4-1-2013 07:46:23 Team X:Team Y:45-70 Final", you will get 8 matches for the regex "\d+". But I only want the scores, so I'd use the regex ":(\d+)-(\d+)" expecting 2 matches, 45 and 70, instead you get ":45-70". (If you forgot the colon, you would get "4-1" and "45-70".)

The groupCount/group(int) methods would have given the expected results, but all the regex grouping rules could make this a newb/novice nightmare. Another option like "Return Regex groups" would be needed to differentiate between using find() and group(int). [Note: group() returns everything matching the entire regex, grouped or not.]

Cool tidbit 1: You can play with grouping to modify a string. In the replace field, groups can be referenced using $1, $2, etc. (group(int)). $0 is the same as group(). So, you could translate text into simple pig latin using "(\w)(\w+)" as the search and "$2-$1ay" as the replace.

Excuse my regexs. It's late. I'm tired. There are errors, but I'm not fixing them.

Also, there is still more not covered here, code-wise... and there is always more to learn about regex.

Ralf Stuckenschnieder

unread,
Apr 17, 2013, 7:00:08 PM4/17/13
to Tasker

I also think it's a problem with the group function.

--
You received this message because you are subscribed to the Google Groups "Tasker" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tasker+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Ralf Stuckenschnieder

unread,
Apr 17, 2013, 7:11:44 PM4/17/13
to Tasker

Teasüti

unread,
Jul 21, 2013, 1:04:57 PM7/21/13
to tas...@googlegroups.com
Any progress on this? I'm a newbie, and I can't figure out how to use this capturing groups.
Also tried the non-capture group, but it also fails to work as expected. I assume a non-capture group should be excluded from match.
I tried to supersede these with Look-around assertions in one expression, but w/o success.
Any help?

Thanks!

Pent

unread,
Jul 22, 2013, 3:32:09 AM7/22/13
to tas...@googlegroups.com
>Any progress on this? I'm a newbie, and I can't figure out how to use this capturing groups.

If I remember right, tou can't access user-captured groups. The Store Matches In variable
gets an entry for each part of the input that matches the whole Search parameter.

If you want to access sub-parts you need to go through all the matches (For loop)
and match those.

Pent

francwalter

unread,
Dec 23, 2013, 8:25:58 AM12/23/13
to tas...@googlegroups.com
Is there now somewhere a better documentation for the Tasker-RegEx?
I want to catch only digits from a sentence, e.g.:

aktuell 8°C bewölkt

I only need the "8"

So I tried Variable Search Replace with:

Variable: %grad (containing above sentence)
Search: .*(\d+).*
One Match Only: yes
Store Matches In: %grad (want to overwrite the %grad with the result, don't need the original %grad anymore)
Replace Matches: no

This gives me the same as input.

I tried then with:

...
Store Matches In: (empty)
Replace Matches: yes
Replace with: $1

and this does the trick.
A short basic intro documentation more than 8 lines in:

http://tasker.dinglisch.net/userguide/en/matching.html

could be save some trial and error time. The difference between \1 and $1 in the "Replace with:" for example I cannot find in the given link:

http://developer.android.com/reference/java/util/regex/Pattern.html

Thank you.
frank




Pent

unread,
Dec 23, 2013, 9:09:59 AM12/23/13
to tas...@googlegroups.com
>Variable: %grad (containing above sentence)
>Search: .*(\d+).*
>One Match Only: yes
>Store Matches In: %grad (want to overwrite the %grad with the result, don't need the original %grad anymore)
>Replace Matches: no

The action help (the ? top right in the action edit screen) says:

"Store Matches In specifies an array variable in which each successive part of the variable which matches the <b>*whole*</b> Search parameter is stored."

Firstly, %grad is treated as an array, meaning successive matches go in %grad1, %grad2 etc
Secondly, note that *whole* is emphasised. Since your match matches the whole input, it matches
only once and the whole input therefore goes in %grad1.

This is not in the 'Pattern Matching' section of the documentation because it's related to how the
action works, whereas regex matching is relevant to several other places in Tasker too.

First thing to do when you have a problem with an action is to read the action help.

Pent

Bob Hansen

unread,
Dec 23, 2013, 9:51:04 AM12/23/13
to tas...@googlegroups.com
Here is a link to an excellent reference for regex.


Also, if you have a PC, I would strongly recommend you get RegexBuddy (free). This is a regex expression builder and I have found it invaluable for learning regex. It can be found here: http://download.cnet.com/RegexBuddy/3000-2352_4-10309844.html

As for selecting the numbers out of your example, use: \d+
The \d matches any digit and the plus (+) tells the regex engine to match all following digits until a non-digit is encountered. (You could just use the \d in your example, but adding the plus is more flexible.)

Hope this helps :>)

PS: If you do use RegexBuddy be sure to set the regex "flavor" to Javascript if your using it with Tasker.

Peter Shannon

unread,
Mar 31, 2014, 10:39:08 PM3/31/14
to tas...@googlegroups.com
This seems to me not to work the way a regex match would be normally expected to work.

Most of the power comes from the ability to match groups. Reading the documentation I initially thought the match variable would be all the marched groups.

Text surrounding the groups is only normally used to place the groups the correct context for the match. Accessing all the matched text is not normally of interest.

Brandon Horwath

unread,
Mar 31, 2014, 11:36:14 PM3/31/14
to tas...@googlegroups.com
The regex Set(Value)? matches Set or SetValue. In the first case, the first (and only) capturing group remains empty. In the second case, the first capturing group matches Value

By placing part of a regular expression inside round brackets or parentheses, you can group that part of the regular expression together. This allows you to apply a quantifier to the entire group or to restrict alternation to part of the regex.

In this sense, I do believe it complies with the norms of regex use based on your input and result.

hippoma...@gmail.com

unread,
Apr 1, 2014, 5:10:16 AM4/1/14
to tas...@googlegroups.com
Tasker uses Java's regular expression semantics, which isn't exactly the same as the egrep and Perl regex's that many people are familiar with.

I don't have time to test this at the moment, but IIRC, the find() method of Matcher does not return smaller subgroups within a larger group.

For example, consider this regex: (a(b(c))). Furthermore, suppose you are matching this string against it: xxxabcxxxabcxxxabcxxx.

I'm pretty sure that looping through the match with find() will iterate 3 times, with each matcher.group() call returning abc, and with the contained subgroups (bc and c) being ignored.
.




hippoma...@gmail.com

unread,
Apr 1, 2014, 5:16:47 PM4/1/14
to tas...@googlegroups.com
Yes, my memory was correct. The program below prints out the following:

+++ abc
+++ abc
+++ abc


import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Junk {
   
    static public void main(String[] argv) {

        Pattern re = Pattern.compile("(a(b(c)))");

        Matcher m = re.matcher("xxxabcyyyabczzzabcqqq");

        while (m.find()) {
            System.out.println("+++ " + m.group());
        }

        System.exit(0);
    }
}

hippoma...@gmail.com

unread,
Apr 1, 2014, 6:31:21 PM4/1/14
to tas...@googlegroups.com
To get the subgroups, you have to do the following (see the program, below). This seems to go beyond Tasker's way of managing regular expressions.

Here's the program's output:

+++ match number 0: abc
    group 0: abc
    group 1: abc
    group 2: bc
    group 3: c
+++ match number 1: abc
    group 0: abc
    group 1: abc
    group 2: bc
    group 3: c
+++ match number 2: abc
    group 0: abc
    group 1: abc
    group 2: bc
    group 3: c


import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Junk {
   
    static public void main(String[] argv) {
        Pattern re = Pattern.compile("(a(b(c)))");
        Matcher m = re.matcher("xxxabcyyyabczzzabcqqq");
        int matchNumber = 0;
        while (m.find()) {
            System.out.println("+++ match number " + matchNumber++ + ": " + m.group());
            int ngroups = m.groupCount();
            for (int n = 0; n <= ngroups; n++) {
                System.out.println("    group " + n + ": " + m.group(n));
            }
        }
        System.exit(0);
    }
}


Peter Shannon

unread,
Apr 4, 2014, 8:48:26 PM4/4/14
to tas...@googlegroups.com

Thanks for looking at this. But my point is that tasker seems to ignore ALL groups not just sub groups. Take a look at the screen shot below (the match is stirred in%result).

The group is ignored, only the matched text is stored.

Screenshot_2014-04-05-08-44-09.jpg

Matt R

unread,
Apr 4, 2014, 9:08:52 PM4/4/14
to tas...@googlegroups.com
This is the way Tasker regex is documented and expected to work.

Matt

hippoma...@gmail.com

unread,
Apr 5, 2014, 5:01:16 AM4/5/14
to tas...@googlegroups.com
On Friday, April 4, 2014 8:48:26 PM UTC-4, Peter Shannon wrote:

Thanks for looking at this. But my point is that tasker seems to ignore ALL groups not just sub groups. Take a look at the screen shot below (the match is stirred in%result).

The group is ignored, only the matched text is stored.


 Yes, it only returns the 0th group (the entire match). You can see that from the code and from the Java documentation for the methods that are being utilized.
.
 

hippoma...@gmail.com

unread,
Apr 5, 2014, 5:05:43 AM4/5/14
to tas...@googlegroups.com
On Friday, April 4, 2014 9:08:52 PM UTC-4, Matt R wrote:
This is the way Tasker regex is documented and expected to work.

Yep. When I get some time, I'll write a plugin which has more regex match/replace capabilities.
.

Peter Shannon

unread,
Apr 5, 2014, 10:43:49 AM4/5/14
to tas...@googlegroups.com

Tasker is a great program and document everything it does is a mammoth task (no pun intended) in itself but I don't think the following is clear, it barely makes sense because the named parts of the dialog aren't marked in a consistent way (Store Matches In, variable, Search):

"Store Matches In specifies an array variable in which each successive part of the variable which matches the *whole* Search parameter is stored."

Perhaps italics or bars would make it clearer that labels in the form are being referenced:

"|Store Matches In| specifies an array variable in which each successive part of the |Variable| which matches the *whole* |Search| parameter is stored."

Peter

On 5 Apr 2014 09:09, "Matt R" <matthew.r...@gmail.com> wrote:
This is the way Tasker regex is documented and expected to work.

Matt

--
You received this message because you are subscribed to a topic in the Google Groups "Tasker" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/tasker/PVtwyQV9An0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to tasker+un...@googlegroups.com.
Visit this group at http://groups.google.com/group/tasker.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages