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

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.

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.

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;

 

Archived

This topic is now archived and is closed to further replies.

×
×
  • 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.