Question

I have text like this from poker software (I have highlighted the parts I need to replace).

--- FLOP --- [Jh 9h Ah]
driverseati checks
darrington has 15 seconds left to act
darrington bets 100
InvisibleEnigma calls 100
driverseati folds
--- TURN --- [Jh 9h Ah] [3c]
darrington bets 200
InvisibleEnigma calls 200
--- RIVER --- [Jh 9h Ah 3c] [Td]

Jh = Jack of hearts
9h = 9 of hearts
Ah = ace of hearts
3c = 3 of clubs

I want to replace the cards inside the square brackets with IMAGES.

So this line: --- TURN --- [Jh 9h Ah] [3c]
Needs to become: --- TURN --- jh.gif 9h.gif ah.gif 3c.gif

I can't figure out the preg_replace :( I can kind of figure it out for just a single card inside brackets (like the [3c]), but I'm stuck at replacing multiple instances on 1 line and some brackets having 3 cards and some brackets having 2, or 1 card.

This is what I have for a single card:

\[([AKQJakqj1-9]0?[DHSCdhsc])\]

Any help would be appreciated.

Was it helpful?

Solution

It's difficult to do if you're looking for the square brackets (as you're finding out). If you don't try to match them and simply look for the card names, wherever they occur, then it's a cinch:

\b([AKQJakqj1-9]0?[DHSCdhsc])\b

The \b markers check for word boundaries. They ensure that the card name must be a distinct word, so Ah in Ahead won't match, for example.

Handling the square brackets quite complicated. Ideally you could use lookahead and lookbehind assertions to check for them, but there's an unfortunate restriction on lookbehind assertions that makes them unsuitable for the job:

The contents of a lookbehind assertion are restricted such that all the strings it matches must have a fixed length.

So instead I came up with a double-replace solution using the /e flag to nest one preg_replace call inside of another.

preg_replace(
    '/\[(.*?)]/e',
    "preg_replace('/(\b[AKQJT1-9]0?[DHSC]\b)/i', '\\\$1.jpg', '$1')",
    $hh
);

The outer regex looks for square brackets and captures the insides. The inner regex looks for card names inside of that $1 and turns them into images.

By the way, I added T to your pattern since 10♦ is typically written as Td in hand histories, and I added the i flag to make the searches case-insensitive.

OTHER TIPS

function imageize($matches)
{
    $from = array('s','c','d','h','[',']');
    $to = array('s.gif','c.gif','d.gif','h.gif','','');
    return $matches[1] . str_replace($from, $to, strtolower($matches[2])) . $matches[3];
}

$str = preg_replace_callback('#([^\[\]]*?)((?: *\[[akqjtcsdh\d ]+\])+)([^\[\]]*?)#i', 'imageize', $str);
$string = "--- RIVER --- [Jh 9h Ah 3c] [Td]";

$CARD = "[akqjt1-9][dhsc]";
echo preg_replace(
  "/\[($CARD(?:\s+$CARD){0,4})\]/ie",
  "preg_replace('/\b$CARD\b/i', '\\\$0.gif', '\$1')",
  $string);

This code outputs:

--- RIVER --- Jh.gif 9h.gif Ah.gif 3c.gif Td.gif


Looks like John (narrowly!) beat me to it while I hacked away, although my code here is a bit more specific - it won't run the replacement on any string inside brackets, like [as the world turns], it has to be a set of cards. I also limited it to 5 cards in brackets, although you could change this by simply adjusting the {0,4} in the match.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top