Jump to content

Compilation failed?


ShadowMage

Recommended Posts

Hey guys, I've got a string I need to split apart and put into an array. I think the preg_split function can do that but I'm having some difficulty getting it to work. I wrote up a quick test and when I ran it, I got the following error:Warning: preg_split() [function.preg-split]: Compilation failed: range out of order in character class at offset 5 in C:\Inetpub\major\Test\JK_Testing.php on line 512Here's the code:

$testString = "{one:1=>3};{two:6;7;8=>4;5;6};{three:text=>test};{four:blah=>blue}";echo "Test string:<br />".htmlentities($testString)."<br />\n";$regex = '/^{[a-Z]+:.+=>.+}$/';$arrValueSets = preg_split($regex, $testString);echo nl2br(print_r($arrValueSets, true));

I think it's a problem with the regex, because I tried changing the regex to:$regex = '/^{.+}$/';and then the error goes away, but $arrValueSets is still an empty array. Can somebody help me with my regex?BTW, the strings I need to match are the parts between the {}. I need it to match {string:any characters=>any characters}

Link to comment
Share on other sites

Solved the error message, but it's still not returning any matches.New code:

$testString = "{one:1=>3};{two:6;7;8=>4;5;6};{three:text=>test};{four:blah=>blue}";echo "Test string:<br />".htmlentities($testString)."<br />\n";$regex = '/^{[A-z]+:.+=>.+}$/';$arrValueSets = preg_split($regex, $testString);echo nl2br(print_r($arrValueSets, true));

Edit: Ooops! Just realized preg_split is using the regex as a delimiter. :) Change my code to this:

$testString = "{one:1=>3};{two:6;7;8=>4;5;6};{three:text=>test};{four:blah=>blue}";echo "Test string:<br />".htmlentities($testString)."<br />\n";$regex = '/^{[A-z0-9]+:.+=>.+}$/';preg_match_all($regex, $testString, $arrMatches);echo nl2br(print_r($arrMatches, true));

but it matches the entire string instead of finding four different strings. Uggh, I don't like regex's :)

Link to comment
Share on other sites

Solved the error message, but it's still not returning any matches.New code:
$testString = "{one:1=>3};{two:6;7;8=>4;5;6};{three:text=>test};{four:blah=>blue}";echo "Test string:<br />".htmlentities($testString)."<br />\n";$regex = '/^{[A-z]+:.+=>.+}$/';$arrValueSets = preg_split($regex, $testString);echo nl2br(print_r($arrValueSets, true));

Try changing:
$regex = '/^{[A-z]+:.+=>.+}$/';

To:

$regex = '/{[a-z]+:.+=>.+}/i';

That's what I would try at least. The main reason it's not getting any matches is probably because you have a caret at the beginning and a dollar sign at the end. A caret at the beginning of a pattern matches the beginning of a string, and a dollar sign at the end matches the very end of a string, which is most likely why it's not finding any matches. "{one:1=>3}" starts at the beginning of the string, but the last curly brace is not at the end of the string, and because you're using "." to match any number of characters with the pattern, it will end up matching the entire string, because it has to match the end of the string due to the dollar sign you put at the end of the pattern.edit:If you're just trying to split the string, a much easier way would be:

$strings = preg_split('/(?<=});(?={)/', $testString);

That would split it up into 4 strings.Otherwise you can use preg_match:

preg_match('/{[a-z]+:.+=>.+}/i', $testString, $m);

And $m will contain all of the matches.

Link to comment
Share on other sites

If you're just trying to split the string, a much easier way would be:
$strings = preg_split('/(?<=});(?={)/', $testString);

That would split it up into 4 strings.Otherwise you can use preg_match:

preg_match('/{[a-z]+:.+=>.+}/i', $testString, $m);

And $m will contain all of the matches.

Yes I'm trying to split the string, but I wanted to try to match the exact pattern since the characters on either side of the '=>' could theoretically be anything. I tried using preg_match_all (as stated in my edit to my last post) but it still matches the entire string (even after removing the ^ and $) which makes sense after reading what you wrote about matching any number of any characters.Hmm....maybe I need to look at a different approach to this..... :)Edit: On second thought, maybe I will give your regex a try (the one you used with preg_split). I tested it out and it does work, so now I think I can use sscanf to extract the parts I need from each string. Thank you, Dilated! :)
Link to comment
Share on other sites

Yes I'm trying to split the string, but I wanted to try to match the exact pattern since the characters on either side of the '=>' could theoretically be anything. I tried using preg_match_all (as stated in my edit to my last post) but it still matches the entire string (even after removing the ^ and $) which makes sense after reading what you wrote about matching any number of any characters.Hmm....maybe I need to look at a different approach to this..... :)
preg_match('/{[a-z]+:.+?=>.+?}/i', $testString, $m);

Try that instead. I forgot to put a question mark after the plus sign when I replied before, my mistake. A question mark after a asterisk or plus sign means that it will try to match the string "ungreedily", meaning it will match as few characters as possible while still completing the pattern matching.Using the preg_split pattern I posted above might be a better way though. Also keep in mind, sometimes the first value of the matches array ($m) that preg_match returns is the initial string you passed into it. So $m[1] might be the first actual match.edit: Fixed the code above, misplaced a question mark. Try it again if you've already tried it. You can also just put a "U" in the modifiers after the delimiters to make everything ungreedy. ie:

preg_match('/{[a-z]+:.+=>.+}/iU', $testString, $m);

Link to comment
Share on other sites

You can also just put a "U" in the modifiers after the delimiters to make everything ungreedy. ie:
preg_match('/{[a-z]+:.+=>.+}/iU', $testString, $m);

Marvelous! That works great. Now I just need to figure out how to extract the information from those strings. I tried using sscanf but it isn't working like I think it should. Here's the code:
$regex = '/{[A-z0-9]+:.+=>.+}/U';preg_match_all($regex, $testString, $arrValueSets);foreach ($arrValueSets[0] as $index => $value) {	echo sscanf($value, "{%s:%s=>%s}", $field, $origVal, $newVal);	echo "<br />Field: ".$field."; ".$origVal."=>".$newVal."<br />";}

It puts the whole string (after the first '{' ) in $field leaving $origVal and $newVal empty.For example, $arrValueSets[0][0] is equal to {one:1=>3}$field will equal one:1=>3}$origVal and $newVal are empty.How can I extract those three values?

Link to comment
Share on other sites

Marvelous! That works great. Now I just need to figure out how to extract the information from those strings. I tried using sscanf but it isn't working like I think it should. Here's the code:
$regex = '/{[A-z0-9]+:.+=>.+}/U';preg_match_all($regex, $testString, $arrValueSets);foreach ($arrValueSets[0] as $index => $value) {	echo sscanf($value, "{%s:%s=>%s}", $field, $origVal, $newVal);	echo "<br />Field: ".$field."; ".$origVal."=>".$newVal."<br />";}

It puts the whole string (after the first '{' ) in $field leaving $origVal and $newVal empty.For example, $arrValueSets[0][0] is equal to {one:1=>3}$field will equal one:1=>3}$origVal and $newVal are empty.How can I extract those three values?

Try this:
preg_match('/{(.+?):(.+?)=>(.+?)}/', $value, $m);list( , $field, $origVal, $newVal) = $m;

Link to comment
Share on other sites

Try this:
preg_match('/{(.+?):(.+?)=>(.+?)}/', $value, $m);list( , $field, $origVal, $newVal) = $m;

You are a regex genius! That works! Thank you. :)Edit: If you don't mind my asking, how exactly does that regex tell preg_match that I want to extract three values? Is it the parens?
Link to comment
Share on other sites

It is, it will return a match for the entire pattern and matches for each of the subpatterns.
So parenthesis define subpatterns then...Cool, thanks jsg. So then what do the parens define in the following regex:$regex = '/(?<={)[A-z0-9]+(?=:\s{1})/';From the following string: {one: 1 => 3}it returns an array with one element: oneThe regex that Dilated gave me returns an array with four elements: {one: 1 => 3}, one, 1, 3Maybe someday I'll get a grasp on these magical strings known as regular expressions...
Link to comment
Share on other sites

Archived

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

×
×
  • Create New...