vb.org Archive

vb.org Archive (https://vborg.vbsupport.ru/index.php)
-   vB3 Programming Discussions (https://vborg.vbsupport.ru/forumdisplay.php?f=15)
-   -   Using preg_match_all... (https://vborg.vbsupport.ru/showthread.php?t=286763)

m002.p 08-17-2012 02:43 PM

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;
I am using a preg_match_all function to retrieve the string pattern into variables.

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;
}

Any help most appreciated.

Matt

kh99 08-17-2012 03:22 PM

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";

m002.p 08-25-2012 09:50 AM

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
I do not understand it; the code examples used are:

Code:

if (preg_match("/\b{$console['chat']}\b/", 'BOT call'))
The above may not be the source of that error but I know for certain that if $console['chat'] was a value of "..." (without quotes), it matches as true? How "..." translates as "BOT call" is beyond me there.

Code:

if (preg_match("/{$ctag}/", $player['name']))
This one always returns true when $ctag = "|SOG|" (without quotes) and the $player['name'] variable contains anything eg. "Matt" or "Tom"... dont understand what is wrong there.

Code:

if (preg_match("/\b{$disresult['names']}\b/", $player['name']))
Lastly not sure if this one is causing the php error but although it appears to work, maybe I am using the wrong context? This example is used within a while mysql_fetch_array query for the variable $disresult['names'].

Is it best I used strpos() instead?

kh99 08-25-2012 12:08 PM

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.

m002.p 08-25-2012 12:22 PM

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 :)

kh99 08-25-2012 12:41 PM

Quote:

Originally Posted by m002.p (Post 2359863)
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']} ?

Oh right, I was getting confused. You do sometimes need those like you said (and they don't hurt even if you don't technically need them - although I think you did need them, like you said). So you would want to take them out of my example since the variable isn't directly in the string any more.

Quote:

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?
That's pretty much the idea, yeah. Sorry, I wasn't sure how much you knew about it. Sometimes people just copy stuff from somewhere else and don't really understand it.


Quote:

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))
?
That looks right.

m002.p 08-25-2012 12:51 PM

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?

kh99 08-25-2012 01:11 PM

Quote:

Originally Posted by m002.p (Post 2359868)
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?

Well, no. It was my mistake - the {} was necessary around the variable name in your original string, and would really be part of the variable name and not part of the pattern, so that was OK. The only issue is that you have to put the variable through preg_quote() unless you're sure it won't contain any meta-characters (unless the variable actually contained a pattern, of course). You could instead do this if you prefered:

Code:

$console['chat'] = preg_quote($console['chat'], '/');
if (preg_match("/\b{$console['chat']}\b/", 'BOT call'))


m002.p 08-26-2012 08:29 AM

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
                }

The $console['chat'] variable as the input contains "BOT report 0;" or "BOT report 0;reason" and for both instances the if statement never works. Lost here...

kh99 08-26-2012 01:27 PM

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)?


All times are GMT. The time now is 10:03 PM.

Powered by vBulletin® Version 3.8.12 by vBS
Copyright ©2000 - 2025, vBulletin Solutions Inc.

X vBulletin 3.8.12 by vBS Debug Information
  • Page Generation 0.01117 seconds
  • Memory Usage 1,759KB
  • Queries Executed 10 (?)
More Information
Template Usage:
  • (1)ad_footer_end
  • (1)ad_footer_start
  • (1)ad_header_end
  • (1)ad_header_logo
  • (1)ad_navbar_below
  • (14)bbcode_code_printable
  • (4)bbcode_quote_printable
  • (1)footer
  • (1)gobutton
  • (1)header
  • (1)headinclude
  • (6)option
  • (1)pagenav
  • (1)pagenav_curpage
  • (1)pagenav_pagelink
  • (1)post_thanks_navbar_search
  • (1)printthread
  • (10)printthreadbit
  • (1)spacer_close
  • (1)spacer_open 

Phrase Groups Available:
  • global
  • postbit
  • showthread
Included Files:
  • ./printthread.php
  • ./global.php
  • ./includes/init.php
  • ./includes/class_core.php
  • ./includes/config.php
  • ./includes/functions.php
  • ./includes/class_hook.php
  • ./includes/modsystem_functions.php
  • ./includes/class_bbcode_alt.php
  • ./includes/class_bbcode.php
  • ./includes/functions_bigthree.php 

Hooks Called:
  • init_startup
  • init_startup_session_setup_start
  • init_startup_session_setup_complete
  • cache_permissions
  • fetch_threadinfo_query
  • fetch_threadinfo
  • fetch_foruminfo
  • style_fetch
  • cache_templates
  • global_start
  • parse_templates
  • global_setup_complete
  • printthread_start
  • pagenav_page
  • pagenav_complete
  • bbcode_fetch_tags
  • bbcode_create
  • bbcode_parse_start
  • bbcode_parse_complete_precache
  • bbcode_parse_complete
  • printthread_post
  • printthread_complete