3

I can use a little help with this regex. The regex below works.

$regexgameid = '/{gameid\s([0-9][0-9][0-9][0-9][0-9])|([0-9][0-9][0-9][0-9][0-9])|([0-9][0-9][0-9][0-9][0-9])}/i';
preg_match_all($regexgameid, $articletext, $matchesgameid, PREG_SET_ORDER);

Example targeted shortcode: {gameid 45735 76352 87262}

The game id's count could be one or three.

With my logic it would be this:

$regexgameid = '/{gameid\s([0-9]{5}){1,3}}/i';
preg_match_all($regexgameid, $articletext, $matchesgameid, PREG_SET_ORDER);

But this regex above doesn't work.


What I'm trying to achieve is to get the results from preg_match_all() in an array structure like this:

Array
(
    [0] => {gameid
    [1] => 45735
    [2] => 76352
    [3] => 87262
    [4] => }
)

so that I can replace the whole {gameid 45735 76352 87262} shortcode in the article text with information about the 3 game ids.

2
  • 3
    Your regex doesn't allow for the space between the numbers. {gameid\s([0-9]{5}\s?){1,3}} possibly Commented Oct 11, 2020 at 8:09
  • What about: (?<game>gameid(?:.\d{5}){1,3})? Commented Oct 11, 2020 at 8:20

2 Answers 2

3

Here is a demonstration of how to use preg_replace_callback() to replace the gameid shortcode tags in your (I assume Joomla) articles.

You state in your question that the number of gameids will either be one or three. For this reason, you should not be using the {1,3} quantifier syntax because that means "one to three" instead of "one or three". In other words, the correct pattern will require that the second and third ids both/neither exist.

The whole shorttag is matched, so all you need to do is dictate the translation in the callback parameter of the native function.

Code: (Demo)

$articleText = <<<TEXT
Some article text
Triple id: {gameid 45735 76352 87262}.
Do not honor {gameid 12345 67890} because contains exactly 2 game ids!
unknown id: {gameid 66666} can't replace it!
Found single id: {gameid 76352}
finished the article
TEXT;

$gamesLookup = [
    45735 => 'Pac-man',
    76352 => 'Donkey Kong',
    87262 => 'Rampage'
];

echo preg_replace_callback(
    '~{gameid (\d{5})(?: (\d{5}) (\d{5}))?}~',
    function ($m) use ($gamesLookup) {
        echo 'm = ' . var_export($m, true) . "\n---\n";
        return 'Game Name(s): ' . strtr(implode(', ', array_slice($m, 1)), $gamesLookup);
    },
    $articleText
);

Output: (I am printing out the matches arrays so you can see the data that you will need to access)

m = array (
  0 => '{gameid 45735 76352 87262}',
  1 => '45735',
  2 => '76352',
  3 => '87262',
)
---
m = array (
  0 => '{gameid 66666}',
  1 => '66666',
)
---
m = array (
  0 => '{gameid 76352}',
  1 => '76352',
)
---
Some article text
Triple id: Game Name(s): Pac-man, Donkey Kong, Rampage.
Do not honor {gameid 12345 67890} because contains exactly 2 game ids!
unknown id: Game Name(s): 66666 can't replace it!
Found single id: Game Name(s): Donkey Kong
finished the article

If you simply want a preg_match_all() call, then the same pattern will suffice...

Code: (Demo)

var_export(
    preg_match_all('~{gameid (\d{5})(?: (\d{5}) (\d{5}))?}~', $articleText, $m, PREG_SET_ORDER)
    ? $m
    : []
);
Sign up to request clarification or add additional context in comments.

Comments

1

There are several problems here. First, your original regex didn't use alternation correctly: this (cut for brevity)...

/{gameid\s([0-9])|([0-9])}/

... actually matches either on {gameid 5} or just on 5 - but never on the whole group. Most likely, that's not what you wanted.

Second, as correctly noted by @NigelRen, there's a whitespace between sequence of digits in your example, but new pattern doesn't cover it.

Here's one approach (assuming you actually need whole GameIDs - and not just digits - stored in $matchesgameid):

$articletext = 'Here is some {gameid 55555 44444 33333} and here is some more {gameid 55555} and this is one more time {gameid 55555 33333}';
$regexgameid = '/{gameid(?:\s[0-9]{5}){1,3}}/i';
preg_match_all($regexgameid, $articletext, $matchesgameid, PREG_SET_ORDER);

Demo. The digit-wrapping group is a non-capturing one here - both to save some performance and to avoid distraction on results. If GameIDs have inconsistent whitespacing (some have ones inside, some don't), just mark \s as optional with ? quantifier:

'/{gameid(?:\s?[0-9]{5}){1,3}}/i';

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.