preg_match_all after hash tag before next hash tag in a string
Asked Answered
A

3

0

I want to find (if they exist) any hash tags and get the first co-occurrence of each tag plus the text after it but before the next tag if another exists.

*Not all message strings carry a hash tag!

Here is what I am trying to do:

List of possible string examples sent to script:

1) $message = 'Added some new stuff';

2) $message = '#BALANCE balanced movement of X';

3) $message = '#CHANGE some log text #FIX some other log text';

$num = prereg_match_all('@?????@', $message, $matches);

This is the array structure result I am aiming for from the matches:

Result of Example 1)

(
[0] => Array
    (
        [0] => Added some new stuff
    )
)

Result of Example 2)

(
[0] => Array
    (
        [0] => balanced movement of X
        [1] => #BALANCE
    )
)

Result of Example 3)

(
[0] => Array
    (
        [0] => some log text
        [1] => #CHANGE
    )
[1] => Array
    (
        [0] => some other log text
        [1] => #FIX
    )
)

Things driving me nuts trying to find decent documentation on REGEX

Aeroneurosis answered 21/6, 2012 at 12:30 Comment(2)
trying to find decent documentation on REGEX - should be something available onlineAshwin
* See also Open source RegexBuddy alternatives and Online regex testing for some helpful tools, or RegExp.info for a nicer tutorial.Fax
A
0

I just got it! After a 3 hour battle, BSDNOOBZ came with the closest answer...

Give it the following cases:

$messages[] = 'Blla vajfkj asfhkha asfha lskahfa';
$messages[] = '#CHANGE reduced sentry health/armor to 325/100 and made them easier to repair with welders #FIX reduced sentry build time to 6 seconds (down from 10)';
foreach($messages AS $message)
{
    $num = preg_match_all('@(\#\w+)([^#]+)@', $message, $matches, PREG_SET_ORDER);
    if($num > 0)
    {
        print_r($matches);
    } else {
        echo $message;
    }
}

Results:

string Blla vajfkj asfhkha asfha lskahfa

Array ( 
    [0] => Array 
    ( 
        [0] => #CHANGE reduced sentry health/armor to 325/100 and made them easier to repair with welders 
        [1] => #CHANGE 
        [2] => reduced sentry health/armor to 325/100 and made them easier to repair with welders 
    ) 
    [1] => Array 
    ( 
        [0] => #FIX reduced sentry build time to 6 seconds (down from 10) 
        [1] => #FIX 
        [2] => reduced sentry build time to 6 seconds (down from 10) 
    )
)
Aeroneurosis answered 21/6, 2012 at 20:52 Comment(0)
D
0

Try this code:

$msg = '#CHANGE some log text #FIX some other log text';
$msg = preg_replace('/(#[\w]+)(\s+)/', "\n\n$1\n", $msg);

foreach (explode("\n\n", trim($msg)) as $k => $v) {
    $res[$k] = array_reverse(explode("\n", $v));
}

print_r($res);
/*
Array
(
    [0] => Array
        (
            [0] => some log text 
            [1] => #CHANGE
        )

    [1] => Array
        (
            [0] => some other log text
            [1] => #FIX
        )

)
*/
Doxia answered 21/6, 2012 at 12:59 Comment(4)
This will fail for the test case that does not include a hashtag.Curley
Nope. Tested with all of the OP's input string and all return as expected.Doxia
My bad - I noticed your regex was specifically looking for hashtags, which wouldn't match ones without it. Also, I didn't run through the extra processing you're doing after preg_replace to see what's going on.Curley
I solved it, bsdnoobz was closest but this silly site wont let me post my answer to my own question for another 6 hours!!!! ......Aeroneurosis
C
0

Try something like this for all of your test cases:

$messages[] = 'Added some new stuff';
$messages[] = '#BALANCE balanced movement of X';
$messages[] = '#CHANGE some log text #FIX some other log text';

foreach( $messages as $message) {
    preg_match_all( '~(#\w+)?\s*([\w\s]+)~i', $message, $matches);
    // var_dump( $matches);
    echo "Message: " . $message . "\n";
    $count = strlen( $matches[1][0]);
    if( $count == 0) {
        // No hash tags
        echo "No hash tags, so the match string text is: " . $matches[2][0] . "\n";
    } else {
        for( $i = 0; $i < count( $matches[1]); $i++) {
            echo "\t Hash tag $i\n";
            echo "\t\t - Tag: ".$matches[1][$i]." Value: ".$matches[2][$i]."\n";
        }
    }
}

This outputs:

Message: Added some new stuff
No hash tags, so the match string text is: Added some new stuff

Message: #BALANCE balanced movement of X
     Hash tag 0
         - Tag: #BALANCE Value: balanced movement of X

Message: #CHANGE some log text #FIX some other log text
     Hash tag 0
         - Tag: #CHANGE Value: some log text 
     Hash tag 1
         - Tag: #FIX Value: some other log text

See it work

Curley answered 21/6, 2012 at 13:1 Comment(0)
A
0

I just got it! After a 3 hour battle, BSDNOOBZ came with the closest answer...

Give it the following cases:

$messages[] = 'Blla vajfkj asfhkha asfha lskahfa';
$messages[] = '#CHANGE reduced sentry health/armor to 325/100 and made them easier to repair with welders #FIX reduced sentry build time to 6 seconds (down from 10)';
foreach($messages AS $message)
{
    $num = preg_match_all('@(\#\w+)([^#]+)@', $message, $matches, PREG_SET_ORDER);
    if($num > 0)
    {
        print_r($matches);
    } else {
        echo $message;
    }
}

Results:

string Blla vajfkj asfhkha asfha lskahfa

Array ( 
    [0] => Array 
    ( 
        [0] => #CHANGE reduced sentry health/armor to 325/100 and made them easier to repair with welders 
        [1] => #CHANGE 
        [2] => reduced sentry health/armor to 325/100 and made them easier to repair with welders 
    ) 
    [1] => Array 
    ( 
        [0] => #FIX reduced sentry build time to 6 seconds (down from 10) 
        [1] => #FIX 
        [2] => reduced sentry build time to 6 seconds (down from 10) 
    )
)
Aeroneurosis answered 21/6, 2012 at 20:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.