Jump to content

preg_replace


sniped22

Recommended Posts

2 advanced (to me anyway) problems that I'm trying to fix...(again!)

1(easy)) using the preg_replace function I have preg_replace($username, $username1, $ph); but I can not figure out how to use the delimiters. Anyone that knows about all that could probably pitch in for this one.

 

2(difficult))

 

throughout the subject (Big data being posted to this page) there are strings that read [Xx Xx] [Xx Xx Xx] [Xx] [Xx Xx] etc. Is there anyway, using preg_replace, that I can make it find [Xx Xx] and replace that with <img src=Xx.bmp><img src=Xx.bmp> Where Xx is a different letter/number every time. There are 52 possible combinations of Xx and I have 52 pictures (cards in a poker deck). So where someone has [As Ac] (ace of spades, ace of clubs) I would like to replace that with [<img src=As.bmp><img src=Ac.bmp>]. I want to somehow find the character "[" and get whatever is after it into a string and then use that string with substr to replace the pictures with Xx.bmp maybe?

 

If you need more clarification, i'll be sittin' here!

Link to comment
Share on other sites

 

I'd split this into two parts.  1)  Find the [Xx Xx] string and extract the stuff between the brackets, and (2) send that Xx Xx Xx stuff to another preg_replace.

 

 

<?php

$text_in = 'blah blah blah [Ac 3d] [10h]';
$text_out = preg_replace_callback(
        '/(\[(?:[AKQJ2-9]|10)[scdh].*?\])/',
        create_function(
                '$x',
                "return preg_replace(
                        '/((?:[AKQJ2-9]|10)[scdh])\s?/',
                        '<img src=\"$1.bmp\">',
                        \$x[0]);"
        ),      
        $text_in
);      

echo "$text_in<br>\n becomes<br>\n$text_out<br>\n";

?>

(Lots of indentation for legibility.)

 

As for delimiters, take a look at the main page for PCRE functions and some of the syntax page.  Delimiters just contain the pattern.  The default ones are '/' as you can see in the patterns I wrote above.  However, they are not required to be that character.  In fact, I think just about ANY character can be used and characters that have "partners" (like parentheses or brackets) can be used in pairs.  (like this)  Note that you'll have to use a '\' to escape the delimiter if you want to use a literal one within the pattern (not as an ending).  I like the pipe character (|) for HTML-heavy patterns sometimes because the usual '/' character needs to be escaped so much.

Link to comment
Share on other sites

alright, well being new to regex (and a decent php programmer) do you have a regex-tutorial or e-book or something of the sort that you picked up when learning regex?

 

for now can you explain a few lines of code?:

 

/(\[(?:[AKQJ2-9]|T)[scdh].*?\])/

for example: This is saying match any AKQJ or number 2-9 or the letter T(i want to know what the "[scdh].*?" does.

I would also like to know why you used create_function inside the preg_replace_callback function and all the stuff inside that function.

It works perfectly, by the way.

 

Thanks again

Link to comment
Share on other sites

I learned regular expressions when I learned Perl.  That's why I'm more comfortable with the PCRE functions that with the ereg ones (but not a big deal since the PCRE's are faster anyway).  So I used "Programming Perl" by Larry Wall; there's a good section in there on regex's.  Of course, O'Reilly also publishes a complete book on regular expressions alone.  Also, the PHP PCRE manual has sections on syntax and modifiers that are also a good reference.  I'm not sure what other references are available on the web, but there's probably some good stuff; just remember that not all regex are the same -- POSIX is different from Perl's, for one.

 

for now can you explain a few lines of code?:

 

/(\[(?:[AKQJ2-9]|T)[scdh].*?\])/

for example: This is saying match any AKQJ or number 2-9 or the letter T(i want to know what the "[scdh].*?" does.

I would also like to know why you used create_function inside the preg_replace_callback function and all the stuff inside that function.

 

I assume then you're using "T" for a ten instead of "10?"  In that case, you can put the T inside the character class and get rid of some stuff:

/(\[[AKQJT2-9][scdh].*?\])/

 

I had to put the "10" outside the character class ([...]) since it consists of two characters and a character class only matches one.

 

From the top...I decided to use two preg_replace's -- one to find the brackets with "Xx" stuff in it, and another to replace the "Xx" themselves since I couldn't think of an easy way to do it in one step.  preg_replace_callback allows the user to make the replacement the output of a function, so I made the function be another preg_replace.  I could have defined the function somewhere with the usual "function blah($x) {..." syntax, but I have a penchant for writing one-liners, and since I wouldn't be using this function anywhere else, why not write it in place?

 

The first regular expression, the one with preg_replace_callback (I'll leave the original in this case since there's more stuff to explain):

(\[(?:[AKQJ2-9]|10)[scdh].*?\])

( - The opening parenthesis "captures" the stuff inside for use in the replacement.
\[ - matches a literal opening square bracket.  It must be escaped since it has a special meaning.
(?: - This opening parenthesis is used for grouping WITHOUT capturing the contents.
[AKQJ2-9] - Is a character class, matching ONE of the characters inside.  Ranges can be defined,
     such as 2-9 (2,3,4,5,6,7,8,9).
|10) - Means "or 10" -- either a character in the class preceeding OR the string "10".  The
     closing parenthesis closes the grouping one -- (?:
[scdh] - Is another character class, matching one of the letters.
.*? - The period is special; it means any character (except newline, but that can be modified).
     The asterisk is a quantifier; it means zero or more.  The question mark makes the quantifier
     "not greedy."
\] - This is the literal closing square bracket.
) - Closing "capture" parenthesis.  Everything inside is captured.

 

By "not greedy" I mean that the regex will stop matching once it hits the first literal square bracket it finds instead of the last that it finds.

 

So, actually, that pattern will match any square brackets that start with the Xx pattern, no matter what else comes after that (because of the .*?).  The pattern could be modified to only match square brackets containing ONLY the Xx-type contents.  Also, I could have put the capturing parens inside the square brackets.  Oh, you know, I didn't need the capturing parens at all, I just realized.  I'll tell you why:

 

Okay, so everything gets passed to the callback function in the same way that a $matches array is set in preg_match -- $matches[0] will have the ENTIRE match, $matches[1] will have the first captured parenthetical expression, $matches[2] the second... etc.  That's why I use $x[0] inside the function; it's an array.  I didn't need to capture a subset since I use the whole thing.

 

The preg_replace inside the callback (I'll explain the current one):

/([AKQJ2-9T][scdh])\s?/

( - Opening capturing parenthesis.
[AKQJ2-9T] - Character class.
[scdh] - Another character class.
) - End capture.
\s - Any whitespace character (space, tab, etc)
? - Quantifier for the whitespace, meaning "zero or more whitespace characters."

 

In this regex two characters are captured ("3s" for example).  The whole matching pattern is replaced, and the captured portion is refered to in the replacement via "$1".  In the example, the replacement becomes: <img src="3s.bmp">.

 

This is slightly improved, in that it won't match the foobar'ed one:

<?php
$text_in = 'blah blah blah [Ac 3d] [Th] [5d 6c foobar]';
$text_out = preg_replace_callback(
        '/\[[AKQJ2-9T][scdh](?:\s+[AKQJ2-9T][scdh])*\]/',
        create_function(
                '$x',
                "return preg_replace(
                        '/([AKQJ2-9T][scdh])\s?/',
                        '<img src=\"$1.bmp\">',
                        \$x[0]);"
        ),
        $text_in
);

echo "$text_in<br>\n becomes<br>\n$text_out<br>\n";
?>

 

How's that?  Long, huh?  :)

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.