Regex match for Pivotal Tracker

169 Views Asked by At

Pivotal Tracker can parse git commits and change ticket status accordingly. I am writing a PHP script that executes post-commit. It searches the commit message and if it finds the right Pivotal Ticket reference it posts it to the PT api. I'm going a bit nuts trying to figure out the regex.

Currently I have:

preg_match('/^\[#([0-9]{1,16})\]/', $commit['message'], $matches);

So the simplest example of a commit passes:

[#12345678] Made a commit

But what I need to pass are the following:

1: [finished #12345678] Made a commit //'fixed', 'complete', or 'finished' changes the status
2: I made a commit [#12345678] to a story //Can occur anywhere in the commit
2

There are 2 best solutions below

1
On BEST ANSWER

The sample inputs are:

I made a commit [#12345678] to a story
[finished #12345678] Made a commit
[fixed #12345678] Made a commit
[complete #12345678] Made a commit

Based on our regex pattern, only the numerical portion is targeted.

To write the best/most efficient pattern to accurately match your input strings, do not use capture groups -- use \K.

/\[[^#]*#\K\d{1,16}/   #just 24 steps

Demo Link


If you need to ensure that the before the #numbers comes either: [nothing], finished, fixed, or complete then this is as refined as I can make it:

/\[(?:fixed ?|finished ?|complete ?)?#\K\d{1,16}/    #59 steps

Demo Link

...this is the same effect as the previous pattern, only condensed slightly:

/\[(?:fi(?:x|nish)ed ?|complete ?)?#\K\d{1,16}/    #59 steps

Demo Link


If these patterns do not satisfy your actual requirements for any reason, please leave a comment and edit your question. I will adjust my answer to create a most-efficient accurate answer for you.

0
On
$string = '2: I made a commit [#12345678] to a story
1: [finished #12345678] Made a commit
3: [fixed #12345678] Made a commit
4: [complete #12345678] Made a commit';

$m = [];
$regex = '/.*\[(finished|fixed|complete)?\s*#(\d+)\]/';

preg_match_all($regex,$string,$m); 

echo '<pre>';
print_r($m);
echo '</pre>';

Should give you

Array
(
[0] => Array
    (
        [0] => 2: I made a commit [#12345678]
        [1] => 1: [finished #12345678]
        [2] => 3: [fixed #12345678]
        [3] => 4: [complete #12345678]
    )

[1] => Array
    (
        [0] => 
        [1] => finished
        [2] => fixed
        [3] => complete
    )

[2] => Array
    (
        [0] => 12345678
        [1] => 12345678
        [2] => 12345678
        [3] => 12345678
    )

)

As you can see the () in the regex expression act as groups which stores the results in an array $m

$m[0] -> stores complete match 
$m[1] -> stores first group () 
$m[2] -> stores second group () 

I think safest way to do this is to process one commit at a time, but this example is just showing you the use cases in the question.