preg_match stops looking after the first match. preg_match_all, on the other hand, continues to look until it finishes processing the entire string. Once match is found, it uses the remainder of the string to try and apply another match.
http://php.net/manual/en/function.preg-match-all.php
Answer from romaninsh on Stack OverflowShould preg_match be checked if it's true or false?
preg match - PHP's preg_match() and preg_match_all() functions - Stack Overflow
[SOLVED] preg_match, preg_match_all and preg_grep
regex - How do I match this pattern using preg_match in PHP? - Stack Overflow
If I'm using preg_match or preg_match_all, should I be check if it returns true or false. For example, I have the following preg_match_all:
$first_match = preg_match_all( '/class=[\'"].+\s+([0-9]+)(.+)?[\'"]/i', $content, $matches );
I subsequently check if it's true like so:
if( $first_match ) {
// Do something}
preg_match stops looking after the first match. preg_match_all, on the other hand, continues to look until it finishes processing the entire string. Once match is found, it uses the remainder of the string to try and apply another match.
http://php.net/manual/en/function.preg-match-all.php
Both preg_match and preg_match_all functions in PHP use Perl compatible regular expressions.
You can watch this series to fully understand Perl compatible regular expressions: https://www.youtube.com/watch?v=GVZOJ1rEnUg&list=PLfdtiltiRHWGRPyPMGuLPWuiWgEI9Kp1w
preg_match($pattern, $subject, &$matches, $flags, $offset)
The preg_match function is used to search for a particular $pattern in a $subject string and when the pattern is found the first time, it stops searching for it. It outputs matches in the $matches, where $matches[0] will contain the text that matched the full pattern, $matches[1] will have the text that matched the first captured parenthesized sub-pattern, and so on.
Example of preg_match()
<?php
preg_match(
"|<[^>]+>(.*)</[^>]+>|U",
"<b>example: </b><div align=left>this is a test</div>",
$matches
);
var_dump($matches);
Output:
array(2) {
[0]=>
string(16) "<b>example: </b>"
[1]=>
string(9) "example: "
}
preg_match_all($pattern, $subject, &$matches, $flags)
The preg_match_all function searches for all the matches in a string and outputs them in a multi-dimensional array ($matches) ordered according to $flags. When no $flags value is passed, it orders results so that $matches[0] is an array of full pattern matches, $matches[1] is an array of strings matched by the first parenthesized sub-pattern, and so on.
Example of preg_match_all()
<?php
preg_match_all(
"|<[^>]+>(.*)</[^>]+>|U",
"<b>example: </b><div align=left>this is a test</div>",
$matches
);
var_dump($matches);
Output:
array(2) {
[0]=>
array(2) {
[0]=>
string(16) "<b>example: </b>"
[1]=>
string(36) "<div align=left>this is a test</div>"
}
[1]=>
array(2) {
[0]=>
string(9) "example: "
[1]=>
string(14) "this is a test"
}
}
You can also use the "glue" feature in your pattern with preg_match_all, this way it's possible to check if the syntax is correct and to extract each part at the same time.
The glue feature ensures that each match follows immediately the previous match without gap. To do that I use the A global modifier (Anchored to the start of the string or the next position after the previous match).
$s = 'q|aaa/aaa|bbb/bbb|ccc/ccc';
$pat = '~ (?!\A) \| \K [^|/]+ / [^|/]+ (?: \z (*:END) )? | \A [^|/]+ ~Ax';
if ( preg_match_all($pat, $s, $m) && isset($m['MARK']) ) {
$result = $m[0];
print_r($result);
}
I use also a marker (*:END) to be sure that the end of the string is well reached despite of the pattern constraints. If this marker exists in the matches array, it's a proof that the syntax is correct. Advantage: you have to parse the string only once (you don't even need to check the whole string syntax in a lookahead assertion anchored at the start of the string).
demo
If you want the whole question as first item in the result array, just write:
$result = array_merge([$s], $m[0]);
So, after the advice, I've decided to use preg_match to check the syntax and then explode to split the string.
This regex seems to match the string format up until any mismatch occurs.
^[^\|/]+(?:\|[^\|/]+/[^\|/]+)+
If I check that the length of the match is the same as the original string I think this will tell me the syntax is correct. Does this sound feasible?
That is a regular expression.
The '^' matches the beginning of a string.
The '\D' matches any character that is not a digit.
The '\d' matches any digit.
The '\s' matches any whitespace.
The plus sign means that the previous character can occur multiple times.
So basically it would match all those lines in your file, except that last comma.
Blue = 1 = No = 20
That line would match the regex.
About your last question to allow numbers too, use this:
/^(.+)\s=\s(\d+)\s=\s(\D+)\s=\s(\d+)/
the code is a regular expression:
/^(\D+)\s=\s(\d+)\s=\s(\D+)\s=\s(\d+)/
the code will use the regular expression to cut the string um pieces and put in an array ($matches)
preg_match('/^(\D+)\s=\s(\d+)\s=\s(\D+)\s=\s(\d+)/', trim($row), $matches);
You shall use the code to see better
print_r($matches)
To find by name or by item number change the code
if(strstr($matches[1], $query))
to
if(isset($matches[1]) && (strstr($matches[1], $query) || $matches[2] == $query) )
Your code shall look like this...
if (isset($_GET['id'])) {
$itemid = $_GET['id'];
$search = "$itemid";
$query = ucwords($search);
$string = file_get_contents('http://clubpenguincheatsnow.com/tools/newitemdatabase/items.php');
if($itemid=="")
{
echo "Please fill out the form.";
}
else
{
$string = explode('<br>',$string);
foreach($string as $row)
{
preg_match('/^(\D+)\s=\s(\d+)\s=\s(\D+)\s=\s(\d+)/', trim($row), $matches);
if(isset($matches[1]) && (strstr($matches[1], $query) || $matches[2] == $query) )
{
echo "<a href='http://clubpenguincheatsnow.com/tools/newitemdatabase/info.php?id=$matches[2]'>";
echo $matches[1];
echo "</a><br>";
}
}
}
}
else {
echo "Item does not exist!";
}
ANYTHING is usually represented by .*? (which you already use in your original regex). You could also use [^"]+ as placeholder in your case.
It sounds like you want the following regular expression:
'/<a href="(http:\/\/example\.org\/.*?)".*?>.*?<\/a>/ms'
You can also use a different delimiter to avoid escaping the backslashes:
'#<a href="(http://example\.org/.*?)".*?>.*?</a>#ms'
Note the escaping of the . in the domain name, as you intend to match a literal ., not any character.