The Arcive of Official vBulletin Modifications Site.It is not a VB3 engine, just a parsed copy! |
|
#1
|
||||
|
||||
Using preg_match_all...
Hi everyone,
I have a string for example like below: Code:
id:3,name:example,ip:89.12.4.54,sa:false,a:false;id:5,name:exampletwo,ip:78.23.45.61,sa:false,a:true; However, the following doesnt seem to work properly. It works when there is one of the pattern but if more than one the array is created incorrectly. I am inexperienced with preg_match_all, anyone spot how to just isolate the pattern correctly? My code: Code:
// Get array function get_vars($var) { $vars = array(); $pattern = "/id:(.*),name:(.*),ip:(.*),sa:(.*),a:(.*);/si"; // This is the pattern to retrieve in the string if (preg_match_all ($pattern , $var, $matches, PREG_SET_ORDER)) { foreach ($matches as $var) { $vars[] = array ( 'id' => $var[1], 'name' => htmlspecialchars_decode(trim($var[2])), 'ip' => $var[3], 'sa' => $var[4], 'a' => $var[5] ); } } return $vars; } Matt |
#2
|
|||
|
|||
The problem is that the * is "greedy" by default, so it will match as much as possible. That's making the first id.*) match all the way to the name: in the last record (because at least one match of that is needed to complete the pattern). You can make the * non-greedy by putting a ? after it, so a pattern like this seems to work:
Code:
$pattern = "/id:(.*?),name:(.*?),ip:(.*?),sa:(.*?),a:(.*?);/si"; Edit: you can also make all matches "ungreedy" by adding the "U" modifier, so this also works: Code:
$pattern = "/id:(.*),name:(.*),ip:(.*),sa:(.*),a:(.*);/siU"; |
#3
|
||||
|
||||
Ah thanks, works a treat. On a similar note, furthering this issue, could you explain the following to me?
I get this message while using preg_match: Code:
PHP Warning: preg_match() [<a href='function.preg-match'>function.preg-match</a>]: Compilation failed: unmatched parentheses at offset 20 Code:
if (preg_match("/\b{$console['chat']}\b/", 'BOT call')) Code:
if (preg_match("/{$ctag}/", $player['name'])) Code:
if (preg_match("/\b{$disresult['names']}\b/", $player['name'])) Is it best I used strpos() instead? |
#4
|
|||
|
|||
I think all your issues have to do with special (meta) characters. Some of the character that are included in your variables have special meaning when in a preg pattern. For instance, and "." means "match any character". You probably know that "\b" means match a word boundary, so when $console['chat'] = "...", the pattern says "match any 3 character word", so it's probably matching "BOT". In the second one you mention, '|' has a special meaning. If you want to know more, it's all explained here: http://us2.php.net/manual/en/referen...ern.syntax.php
You could solve that by using the function preg_quote(), which makes sure that any special characters are 'escaped'. So for instance, your first example would be: Code:
if (preg_match('/\b{' . preg_quote($console['chat'], '/') . '}\b/', 'BOT call')) I left in the { and } chars, I don't know if you want to match those or if they were just there to surround the variable. If you don't want them to match something, then you should take them out (they have another special meaning in patterns, and aren't used to enclose variables). However, like you mentioned, if you have no need of the "power" of the preg functions, you should use strpos or something like that. I notice that a couple of your patterns have "\b" - if it's important that you only match the separate word (and if it could be at the start or end so it may or may not have a space before and after it), then you may need a preg function. It's hard to say without knowing exactly what you're doing. |
#5
|
||||
|
||||
I was using the { } characters to enclose the variable as I have done in a mysql query for any variables like $array['offset'];
Do you not need to enclose variables? Is there documentation to understand when and when not to enclose in either ".$var['name']." or {$var['name']} ? I thought \b meant exact word search? So for example "I have a string" passed through preg_match with this \b searching for "in" would be false, whereas without the \b it would be true? Lastly what is the syntax for the above preg_quote example you provided without the \b? Code:
if (preg_match('/' . preg_quote($player['name'], '/') . '/', $ctag)) Thanks so much for your help, I am learning alot about preg_match. I was always used to ereg before it died in PHP 5 |
#6
|
|||
|
|||
Quote:
Quote:
Quote:
|
#7
|
||||
|
||||
Thanks.
So finally, is it best to use the ". instead of {} for variables directly in the preg_match function to avoid the {} being used as part of the search critera? |
#8
|
|||
|
|||
Quote:
Code:
$console['chat'] = preg_quote($console['chat'], '/'); if (preg_match("/\b{$console['chat']}\b/", 'BOT call')) |
#9
|
||||
|
||||
Kh99,
I have one preg_match I simply cannot get to work as true in this if statement. Any ideas? Code:
// Check for player reports $p1 = "/BOT report (.*);(.*)/"; if (preg_match_all($p1, $console['chat'], $out1)) { // Do Something } |
#10
|
|||
|
|||
It looks right to me, and this test program seems to work:
Code:
<?php $str = "BOT report 0;" or "BOT report 0;reason"; $p1 = "/BOT report (.*);(.*)/"; if (preg_match_all($p1, $str, $out1)) { echo "<pre>"; print_r($out1); echo "</pre>"; } else echo "No match"; $str = "BOT report 0;reason"; if (preg_match_all($p1, $str, $out1)) { echo "<pre>"; print_r($out1); echo "</pre>"; } else echo "No match"; Are you sure that's exactly what's in $console['chat']? For instance, is there just one space between the words (and not tabs or anything)? |
|
|
X vBulletin 3.8.12 by vBS Debug Information | |
---|---|
|
|
More Information | |
Template Usage:
Phrase Groups Available:
|
Included Files:
Hooks Called:
|