preg_match_all not working with mysql database results variables? - php

-- update --
Ok, I've narrowed this down to the keywords being checked, The keywords will only match with spaces between them if they are hard coded in to the array. If the keywords with spaces are placed in to the array are results from a database then the preg_match_all fails with 0 results found.
So if I hard code the array in php like
$myarray = array("This is my Phrase","This is my Second Phrase");
and then check it against the texttoscan the preg_match_all will find both phases, but
if i do this to create the array:
$result1 = mysql_result($result,$i,"firstphrase");
$result2 = mysql_result($result,$i,"secondphrase");
$myarray = array($result1,$result2);
The preg_match_all below will fail and not find the phrases, but if I populate the array with single words instead of phrases it will work. So I assume I have to prepare the strings that contain spaces that are returned from the database, but I'm not exactly sure how to do it, either that or I need to reformat the regex pattern?
foreach ($myarray as $K) {
$pattern = "/\b($K)\b/";
$count = preg_match_all($pattern, $texttoscan, $matches);
if($count > 0){ echo "matched"; }
}

Is it possible that the database text contains line breaks, where the hard-coded text didn't? If so, you would want to use the m modifier to allow multi-line matching. That would make the regular expression:
$pattern = "/\b($K)\b/m";
Hope that helps. Also, unless you are trying to specifically match UTF words/characters you shouldn't have any problem with that.

Related

RegEx for capturing digits in a string (PHP)

I am pulling in job numbers and matching them to data in a mysql database, then retrieving the matching data.
If my job number is 123456 then it matches up fine and I get results.
Some are 123-456 some are 12-text, while some are 12-text-345
$variable = $variable
I tried matching the variable but that's what's not effective.
I tried changing the SQL within PHPMyAdmin and it doesn't even work smoothly there.
I googled and think I should be using RegExp. I tried. I can add a slash and make it work on individual items, however, I do not know where the hyphen will be amidst a massive array. It might be the third or fourth character.
I tried pregmatch but I don't think I know what I'm doing with that.
I'm looking for a few lines of code to analyze a PHP variable and both detect and escape any meta characters if there are any. A tutorial link would be fine too, I appreciate any assistance
Here, if we wish to only get the numbers, on way would be to collect our digits in a capturing group and then collect everything else, then replace it with just $1, with an expression similar to:
(\d+)|\D+
Test
$re = '/(\d+)|\D+/m';
$str = 'text-12-text-345';
$subst = '$1';
$result = preg_replace($re, $subst, $str);
echo $result;
Output
12345
DEMO

preg_replace - similar patterns

I have a string that contains something like "LAB_FF, LAB_FF12" and I'm trying to use preg_replace to look for both patterns and replace them with different strings using a pattern match of;
/LAB_[0-9A-F]{2}|LAB_[0-9A-F]{4}/
So input would be
LAB_FF, LAB_FF12
and the output would need to be
DAB_FF, HAD_FF12
Problem is, for the second string, it interprets it as "LAB_FF" instead of "LAB_FF12" and so the output is
DAB_FF, DAB_FF
I've tried splitting the input line out using 2 different preg_match statements, the first looking for the {2} pattern and the second looking for the {4} pattern. This sort of works in that I can get the correct output into 2 separate strings but then can't combine the two strings to give the single amended output.
\b is word boundary. Meaning it will look at where the word ends and not only pattern match.
https://regex101.com/r/upY0gn/1
$pattern = "/\bLAB_[0-9A-F]{2}\b|\bLAB_[0-9A-F]{4}\b/";
Seeing the comment on the other answer about how to replace the string.
This is one way.
The pattern will create empty entries in the output array for each pattern that fails.
In this case one (the first).
Then it's just a matter of substr.
$re = '/(\bLAB_[0-9A-F]{2}\b)|(\bLAB_[0-9A-F]{4}\b)/';
$str = 'LAB_FF12';
preg_match($re, $str, $matches);
var_dump($matches);
$substitutes = ["", "DAB", "HAD"];
For($i=1; $i<count($matches); $i++){
If($matches[$i] != ""){
$result = $substitutes[$i] . substr($matches[$i],3);
Break;
}
}
Echo $result;
https://3v4l.org/gRvHv
You can specify exact amounts in one set of curly braces, e.g. `{2,4}.
Just tested this and seems to work:
/LAB_[0-9A-F]{2,4}/
LAB_FF, LAB_FFF, LAB_FFFF
EDIT: My mistake, that actually matches between 2 and 4. If you change the order of your selections it matches the first it comes to, e.g.
/LAB_([0-9A-F]{4}|[0-9A-F]{2})/
LAB_FF, LAB_FFFF
EDIT2: The following will match LAB_even_amount_of_characters:
/LAB_([0-9A-F]{2})+/
LAB_FF, LAB_FFFF, LAB_FFFFFF...

Explode based on special characters

I have an issue where, I am not able to explode based on database values.
my database values can be as such
1-10
< 10
">20
I want to explode based on specail characters and put them in an array.
for example
$array = explode("/ (-) "/, Model::find()->findByPj($model->id));
How do I get the regex for that to explode dynamically based on the data
explode() can't handle regular expressions. You are looking for preg_split() and the correct pattern is (-|<|>). The pattern basically means: match - or < or >.
So the code should look like this:
$array = preg_split("/ (-|<|>) /", Model::find()->findByPj($model->id));
You can use preg_split(regex_pattern, string) like this:
$array = preg_split("(-)", 'some string here, lorem-ipsum');
var_dump($array);
Hope this helps!

I need to find a way explode a specific string that has quotes in it

I'm having serious trouble with this and I'm not really experienced enough to understand how I should go about it.
To start off I have a very long string known as $VC. Each time it's slightly different but will always have some things that are the same.
$VC is an htmlspecialchars() string that looks something like
Example Link... Lots of other stuff in between here... 80] ,[] ,"","3245697351286309258",[] ,["812750926... and it goes on ...80] ,[] ,"","6057413202557366578",[] ,["103279554... and it continues on
In this case the <a> tag is always the same so I take my information from there. The numbers listed after it such as ,"3245697351286309258",[] and ,"6057413202557366578",[] will also always be in the same format, just different numbers and one of those numbers will always be a specific ID.
I then find that specific ID I want, I will always want that number inside pid%3D and %26oid.
$pid = explode("pid%3D", $VC, 2);
$pid = explode("%26oid", $pid[1], 2);
$pid = $pid[0];
In this case that number is 6057413202557366578. Next I want to explode $VC in a way that lets me put everything after ,"6057413202557366578",[] into a variable as its own string.
This is where things start to break down. What I want to do is the following
$vinfo = explode(',"'.$pid.'",[]',$VC,2);
$vinfo = $vinfo[1]; //Everything after the value I used to explode it.
Now naturally I did look around and try other things such as preg_split and preg_replace but I've got to admit, it is beyond me and as far as I can tell, those don't let you put your own variable in the middle of them (e.g. ',"'.$pid.'",[]').
If I'm understanding the whole regular expression idea, there might be other problems in that if I look for it without the $pid variable (e.g. just the surrounding characters), it will pick up the similar parts of the string before it gets to the one I want, (e.g. the ,"3245697351286309258",[]).
I hope I've explained this well enough, the main question though is - How can I get the information after that specific part of the string (',"'.$pid.'",[]') into a variable?
I hope this does what you want:
pid%3D(?P<id>\d+).*?"(?P=id)",\[\](?P<vinfo>.*?)}\);<\/script>
It captures the number after pid%3D in group id, and everything after "id",[] (until the next occurence of });</script>) in group vinfo.
Here's a demo with shortened text.
The problem of capturing more than you want is fixed using capture groups. You'll wrap part of a regular expression in parenthesis to capture it.
You can use preg_match_all to do more robust regular expression capture. You will get an array of things that contains matches to the string that matched the entire pattern plus a string with a partial match for each capture group you use. We'll start by capturing the parts of the string you want. There are no capture groups at this point:
$text = 'Example Link... Lots of other stuff in between here... 80] ,[] ,"","3245697351286309258",[] ,["812750926... and it goes on ...80] ,[] ,"","6057413202557366578",[] ,["103279554... and it continues on"';
$pattern = '/,"\\d+",\\[\\]/';
preg_match_all($pattern,
$text,
$out, PREG_PATTERN_ORDER);
echo $out[0][0]; //echo ,"3245697351286309258",[]
Now to get just the pids into a variable, you can add a capture group in your pattern. The capture group is done by adding parenthesis:
$text = ...
$pattern = '/,"(\\d+)",\\[\\]/'; // the \d+ match will be capture
preg_match_all($pattern,
$text,
$out, PREG_PATTERN_ORDER);
$pids = $out[1];
echo $pids[0]; // echo 3245697351286309258
Notice the first (and only in this case) capture group is in $out[1] (which is an array). What we have captured is all the digits.
To capture everything else, assuming everything is between square brackets, you could match more and capture it. To address the question, we'll use two capture groups. The first will capture the digits and the second will capture everything matching square brackets and everything in between:
$text = ...;
$pattern = '/,"(\\d+)",\\[\\] ,(\\[.+?\\])/';
preg_match_all($pattern,
$text,
$out, PREG_PATTERN_ORDER);
$pids = $out[1];
$contents = $out[2];
echo $pids[0] . "=" . $contents[0] ."\n";
echo $pids[1] . "=". $contents[1];

str_replace matches incorrect part of string

I'm having some issues with str_replace, when trying to automatically put backticks around table- and fieldnames.
Assuming i have the following arrays:
$match = array('rooms.roomID','r_rooms.roomID');
$replace = array('`rooms`.`roomID`','`r_rooms`.`roomID`');
$subject = 'rooms.roomID = r_rooms.roomID';
str_replace($match,$replace,$subject);
The result that I expect is:
`rooms`.`roomID` = `r_rooms`.`roomID`
But instead I'm getting this:
`rooms`.`roomID` = r_`rooms`.`roomID`
However if i change r_rooms to r_ooms, my result is as expected
`rooms`.`roomID` = `r_ooms`.`roomID`
I've tried the same precedure, using preg_replace, but this gives me the same output aswell.
Quick fix would be reordering $match and $replace arrays like this...
$match = array('r_rooms.roomID', 'rooms.roomID');
$replace = array('`r_rooms`.`roomID`', '`rooms`.`roomID`');
The problem of the original approach is that str_replace processes $match array element by element, at each step trying to cover the whole string - and replaces the found parts immediately.
As rooms.roomID string 'matches' both [rooms.roomID] and r_[rooms.roomID], and replaces these accordingly, the second iteration will have nothing to do.
As I said, that's only a quick fix. In this case I'd try to use preg_replace instead, surrounding the actual search with \b (word boundary anchors).
Then again, with all due respect I smell XY problem here. Aren't you trying to make your own routine for quoteIdentifier? That was already solved (and asked here a lot of times).
It is correct. First replaced value is rooms.roomID to rooms.roomID (2 times)
Change order of $match and $replace tables to get expected result
$match = array('r_rooms.roomID','rooms.roomID');
$replace = array('`r_rooms`.`roomID`','`rooms`.`roomID`');

Categories