preg_replace multiple instances on 1 line?
I have text like this from poker software (I have highlighted the parts I need to replace).
--- FLOP --- 开发者_Go百科[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.gifI 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.
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.
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.
精彩评论