Jump to content

preg_match Matching Only First and Last Result


cassiusA

Recommended Posts

Hi,

 

I'm trying to learn some php and have hit a stumbling block on something I'm working on.  I have a string that contains the following value: {Cats|Dogs|Mice} and a {Monkey|Chimp}  I would like to randomly select 1 item from each group of animals.  So results would look like "Cats and a Monkey" or "Mice and a Chimp" for example.

 

This is the code I currently have written to get started, but it's not quite doing what I expected.

 

<?php
$content_str = "{Cats|Dogs|Mice} and a {Monkey|Chimp}";
preg_match("|{(.+)}|si", $content_str, $inside);

$contents = preg_split('/\|/', $inside[1], -1, PREG_SPLIT_OFFSET_CAPTURE);
$pieces = explode("|", $inside[1]);

$result = count($contents);
$word = $pieces[rand(0, $result-1)];
echo $inside[1];
?>

 

Obviously my code is incomplete for the examples above.  At this point, I was kind of expecting to see something like: "Cats|Dogs|Mice and a Monkey|Chimp" or "Cats|Dogs|Mice and a {Monkey|Chimp}"

 

What I'm actually getting is "Cats|Dogs|Mice} and a {Monkey|Chimp"

 

So my code is finding and removing the correct characters ( '{' and '}' ), however it's only removing the first and the last.  Ideally, I'd like for it to remove every set and put each sequence of words, cats|dogs|mice for example, into an array so I can call them directly.

 

Any ideas about what I need to do, or of a better way going about doing this?

 

Cheers

Link to comment
Share on other sites

it's because you are using a greedy quantifier (.+)    so it matches all the way to the last instance of }  instead of (.+) make it lazy by doing (.+?) or better yet, use a negative character class: ([^}]+)

 

couple other things: preg_match() only matches first instance, I'm not 100% sure what you're trying to accomplish but you will probably want to change that to preg_match_all().

 

Also, after the preg_match you are using preg_split to further break down the values...but since you are just using | as a delim (a static delimiter) you should be better off just using explode for that bit.

Link to comment
Share on other sites

Thank you for the fantastic (and fast!) feedback, Crayon Violent.

 

Given what you've suggested, I guessing it should look something more like this then.

 

Untested

preg_match_all('|({[^}]+})|', $content_str, $inside, PREG_PATTERN_ORDER);

 

As for using explode, I will definitely use that moving forward.  I wasn't even aware of it's existence.

Link to comment
Share on other sites

Here's a brief example which uses preg_replace_callback and a bespoke callback function to replace the tags with one of the words at random.

 

 

function choose_word($match) {    $options = explode('|', $match[1]);    return $options[array_rand($options)];}$subject = "{Cats|Dogs|Mice} and a {Monkey|Chimp}";$phrase  = preg_replace_callback('/{([^{}]+)}/', 'choose_word', $subject);echo $phrase;

 

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.