preg_match just returns 'Array'? - php

when using this code to fetch data from http://www.ea.com/uk/football/profile/Calfreezy/360 the code just echo's back the word 'Array'
Here is the code I'm using currently:
<?php
$content = file_get_contents("http://www.ea.com/uk/football/profile/Calfreezy/360");
preg_match('#<div class="stat">Titles Won<span>([0-9\.]*)<span class="sprite13 goalImage cup"></span></span>#', $content, $titleswon);
echo 'Titles Won: '.$titleswon.'';
?>
And this is the HTML I am trying to pull from the url:
<div class="stat">
Titles Won <span>0<span class="sprite13 goalImage cup"></span></span>
</div>
This is just returning Titles won: Array
When if working it should return Titles won: 0
What am I doing wrong, thanks.

You are printing the entire matches array instead of selecting the index(es) that you want from it and printing them.
See the documentation
If matches is provided, then it is filled with the results of search. $matches[0] will contain the text that matched the full pattern, $matches[1] will have the text that matched the first captured parenthesized subpattern, and so on.

preg_match() produces an array of matches. If you print out an array in string context, you get Array as the text. e.g.
$arr = array('foo' => 'bar');
echo $arr; // prints "Array"
echo $arr['foo']; // prints "bar"

preg_match returns an array as can be seen from the documentation.
if you want to see all the contents of the array use
var_dump( $titleswon );
If you just need the matched, you have to address that specific part.

The best approach would be :
if (preg_match('#<div class="stat">Titles Won<span>([0-9\.]*)<span class="sprite13 goalImage cup"></span></span>#', $content, $titleswon)) {
echo 'Titles Won: '.$titleswon[1].'';
}

The third param tho preg_match is passed by reference and will contain an array with matches in every capture group. You are using two "groups". The whole match and ([0-9\.]*) which will be the second. So I expect you need this:
echo 'Titles Won: '.$titleswon[1].''; // note the array is indexed by 0

If you have a look to the preg_match documentation:
http://php.net/manual/en/function.preg-match.php
You can see that in the $match argument is actually an array, $match[0] containing the whole match, and the consecutive array elements containing the subqueries.
If you do var_dump($titleswon) or print_r($titleswon) you will see the whole information, then you can access to the desired info, in your case it would be $titleswon[1]

Related

check if array has this value and then grab it and place it an a variable

I have a string like the one below
20Nov 18:14:xxxxxxxxxx has given 10 points to xxxxx. New bitcoin collection Balance:XXXXXXXX. Ref:675743957424
I will explode it and it will then be turned into an array.
But I want to check if the array has Ref:675743957424 and then place it inside a variable like for example $a.
I want to do this since the string might change from one point to another so the position of Ref is not fixed.
How Can i obtain such thing?
Thanks.
Edited
I tried not exploding it but instead try grabbing the data see code below
<?php
$line = "20Nov 18:14:xxxxxxxxxx has given 10 points to xxxxx. New bitcoin collection Balance:XXXXXXXX. Ref:675743957424";
// perform a case-Insensitive search for the word "Vi"
if (preg_match("/\bRef\b/i", $line, $match)) :
print "Match found!";
//how can I grab the Ref part?
endif;
?>
You have to use:
preg_match ('/Ref:[\d]*/', $line, $matches);
The matches will be saved to variable $matches and then you can operate with said matches.
The RegExp, you just need to look for string Ref: followed by any amount of numbers (\d looks for any digit and * looks for zero or more ocurrences of the previous operator, digits in this case).
If you know the exact number of digits that you must to find and it is not varying you could use the pattern {NUMBER}, like:
preg_match ('/Ref:[\d]{12}/', $line, $matches);
This case, you are looking for 12 digits after Ref:.
You can use strpos() to check whether the substring present in the string. If it is true, you can assign that to your variabble. Pleas see the below code, it may help you.
$line = "20Nov 18:14:xxxxxxxxxx has given 10 points to xxxxx. New bitcoin collection Balance:XXXXXXXX. Ref:675743957424";
$string_to_check ='Ref:675743957424'
if (strpos($line,$string_to_check) !== false) { //Ref is present
$a = $line;
}

Regular expression match formatted text in PHP

I have formatted text like this:
Record
name=aaa
age=16
info=blabla bla
Record
name=bbb
age=15
info=foo bar foo bar
Would like to convert it into arrays with regular expression in PHP. So far I've tried:
preg_match_all("/Record.*\n(?m:^(.+)=(.+)$)+/",$text,$matches);
But it only catches "Record name=aaa" and "Record name=bbb"
Wondering why the + does not work in this case. So how should I form my pattern here?
You have not matched the newlines after the first. Move the \n inside the (?m:...) section
This will do it.
$data = array_values(array_map(
function($e){
preg_match_all('/(.*?)=([^\r\n]*)/', $e, $m);
return array_combine($m[1], $m[2]);
},
array_filter(explode("Record", $text))
));
First it splits the whole data by Record as delimiter using explode and array_filter. Then for each of the chunk it extracts the key-value pair using preg_match_all and constructs an associative array (by array_combine).

Using PHP's preg_match to see if a value matches a list of values

I want to see if a variable contains a value that matches one of a few values in a hard-coded list. I was using the following, but recently found that it has a flaw somewhere:
if (preg_match("/^(init)|(published)$/",$status)) {
echo 'found';
} else {
echo 'nope';
}
I find that if the variable $status contains the word "unpublished" there is still a match even though 'unpublished' is not in the list, supposedly because the word 'unpublished' contains the word 'published', but I thought the ^ and $ in the regular expression are supposed to force a match of the whole word. Any ideas what I'm doing wrong?
Modify your pattern:
$pattern = "/^(init|published)$/";
$contain = "unpublished";
echo preg_match($pattern, $contain) ? 'found' : 'nope' ;
This pattern says our string must be /^init$/ or /^published$/, meaning those particular strings from start to finish. So substrings cannot be matched under these constraints.
In this case, regex are not the right tool to use.
Just put the words you want your candidate to be checked against in an array:
$list = array('init', 'published');
and then check:
if (in_array($status, $list)) { ... }
^ matches the beginning of a string. $ matches the end of a string.
However, regexes are not a magic bullet that need to get used at every opportunity.
In this case, the code you want is
if ( $status == 'init' || $status == 'published' )
If you are checking against a list of values, create an array based on those values and then check to see if the key exists in the array.

Replace text within brackets with thus-named variable in PHP

I want to replace all strings in square brackets ([]) with a randomly chosen item from an array that's named that string.
It's very similar to this issue, but with a twist, in that I want to replace different brackets' contents with strings from arrays named that.
An example should make this a bit clearer.
So say I've got the string
"This is a very [adjective] [noun], and this is a [adjective] [noun]."
And the variables:
$adjective = array("big","small","good","bad");
$noun = array("house","dog","car");
And we want it to return "This is a very big house, and this is a good dog." or whatever, by choosing randomly. That is, I want to write a PHP function that will replace each [string] with a randomly chosen item from the array named $string. For now it doesn't matter if by randomly choosing it ends up repeating choices, but it must make a fresh choice for each [] item.
I hope I've explained this clearly. If you get what I'm trying to achieve and can think of a better way to do it I'd be very grateful.
Algorithm
Match for this regex: (\[.*?\])
For each match group pick an item from the related array.
Replace in string by order.
Implementation
$string = "This is a very [adjective] [noun], and this is a [adjective] [noun].";
$adjective = array("big","small","good","bad");
$noun = array("house","dog","car");
// find matches against the regex and replaces them the callback function.
$result = preg_replace_callback(
// Matches parts to be replaced: '[adjective]', '[noun]'
'/(\[.*?\])/',
// Callback function. Use 'use()' or define arrays as 'global'
function($matches) use ($adjective, $noun) {
// Remove square brackets from the match
// then use it as variable name
$array = ${trim($matches[1],"[]")};
// Pick an item from the related array whichever.
return $array[array_rand($array)];
},
// Input string to search in.
$string
);
print $result;
Explanation
preg_replace_callback function performs a regular expression search and replace using provided callback function.
First parameter is regular expression to match (enclosed between slashes): /(\[.*?\])/
Second parameter is callback function to call for each match. Takes the current match as parameter.
We have to use use() here to access the arrays from inside the function, or define the arrays as global: global $adjective = .... Namely, we have to do one of the followings:
a) Define arrays as global:
...
global $adjective = array("big","small","good","bad");
global $noun = array("house","dog","car");
...
function($matches) {
...
b) Use use:
...
$adjective = array("big","small","good","bad");
$noun = array("house","dog","car");
...
function($matches) use ($adjective, $noun) {
...
First line of the callback function:
trim: Removes square brackets ([]) from the match using trim function.
${}: Creates a variable to use as array name with the match name. For example, if the $match is [noun] then trim($matches[1],"[]") returns noun (without brackets) and ${noun} becomes the array name: $noun. For more information on the topic, see variable variables.
Second line randomly picks an index number available for the $array and then returns the element at this position.
Third parameter is the input string.
The code below will do the work:
$string = "This is a very [adjective] [noun], and this is a [adjective] [noun]."
function replace_word ( $matches )
{
$replaces = array(
'[adjective]' => array("big", "small", "good", "bad"),
'[noun]' => array("house", "dog", "car")
);
return $replaces[$matches[0]][array_rand($replaces[ $matches[0] ])];
}
echo preg_replace_callback("(\[.*?\])", "replace_word", $string);
First, we regular expression match on the [something] parts of the word, and call the replace_word() callback function on it with preg_replace_callback(). This function has an internal $replaces two dimension deep array defined inside, each row defined in a [word type] => array('rep1', 'rep2', ...) format.
The tricky and a bit obfuscated line is the return $replaces[$matches[0]][array_rand($replaces[ $matches[0] ])];. If I chunk it down a bit, it'll be a lot more parsable for you:
$random = array_rand( $replaces[ $matches[0] ] );
$matches[0] is the word type, this is the key in the $replaces array we are searching for. This was found by regular expression in the original string. array_rand() basically selects one element of the array, and returns its numerical index. So $random right now is an integer somewhere between 0 and the (number of elements - 1) of the array containing the replaces.
return $replaces[ $matches[0] ][$random];
This will return the $randomth element from the replace array. In the code snippet, these two lines are put together into one line.
Showing one element only once
If you want disjunct elements (no two adjective or noun repeated twice), then you will need to do another trick. We will set the $replaces array to be defined not inside the replace_word() function, but outside it.
$GLOBALS['replaces'] = array(
'[adjective]' => array("big", "small", "good", "bad"),
'[noun]' => array("house", "dog", "car")
);
Inside the function, we will set the local $replaces variable to be a reference to the newly set array, with calling $replaces = &$GLOBALS['replaces'];. (The & operator sets it a reference, so everything we do with $replaces (remove and add elements, for example) modifies the original array too. Without it, it would only be a copy.)
And before arriving on the return line, we call unset() on the currently to-be-returned key.
unset($replaces[$matches[0]][array_rand($replaces[ $matches[0] ])]);
The function put together now looks like this:
function replace_word ( $matches )
{
$replaces = &$GLOBALS['replaces'];
unset($replaces[$matches[0]][array_rand($replaces[ $matches[0] ])]);
return $replaces[$matches[0]][array_rand($replaces[ $matches[0] ])];
}
And because $replaces is a reference to the global, the unset() updates the original array too. The next calling of replace_word() will not find the same replace again.
Be careful with the size of the array!
Strings containing more replace variables than the amount of replace values present will throw an Undefined index E_NOTICE. The following string won't work:
$string = "This is a very [adjective] [noun], and this is a [adjective] [noun]. This is also an [adjective] [noun] with an [adjective] [noun].";
One of the outputs look like the following, showing that we ran out of possible replaces:
This is a very big house, and this is a big house. This is also an small with an .
Another good (easier) method of doing this (not my solution)
https://stackoverflow.com/a/15773754/2183699
Using a foreach to check on which variables you want to replace and replacing them with
str_replace();
You can use preg_match and str_replace function to achive this goal.
First find the matches using preg_match function and then create search & replace array from the result.
Call str_replace function by passing the previous arrays as parameters.
This is my minor update to mmdemirbas' answer above. It lets you set the variables outside of the function (i.e. use globals, as said).
$result = preg_replace_callback(
// Matches parts to be replaced: '[adjective]', '[noun]'
'/(\[.*?\])/',
// Callback function. Use 'use()' or define arrays as 'global'
function($matches) use ($adjective, $noun) {
// Remove square brackets from the match
// then use it as variable name
$arrayname = trim($matches[1],"[]");
$array = $GLOBALS[$arrayname];
// Pick an item from the related array whichever.
return $array[array_rand($array)];
},
// Input string to search in.
$string
);
print $result;

preg_math multiply responce

<?php
$string = "Movies and Stars I., 32. part";
$pattern = "((IX|IV|V?I{0,3}[\.]))";
if(preg_match($pattern, $string, $x) == false)
{
print "NAPAKA!";
}
else
{
print_r($x);
}
?>
And the response is:
Array ( [0] => I. [1] => I. )
I should get only 1 response... Why do I get multiple responses?
The element at index 0 is the whole matched string. The element at index 1 is the contents of the first capture group, i.e. the content inside the parenthesis. In this case, they just happen to be the same. Just use $x[0] to get the value you're looking for.
The nested parenthesis should, in this instance, be a "non-capturing" subpattern.
$pattern = "~((?:IX|IV|V?I{0,3}[\.]))~";
Try that. It will tell the regex compiler to not capture the results of those parenthesis into the array.
In fact, looking at your regex, you don't even need those parenthesis. Make your regex this:
$pattern = "~IX|IV|V?I{0,3}[\.]~";
That should also work.
Your pattern has multiple groups in it -> the () brackets tell you what to capture in your match.
Try this:
$pattern = "(IX|IV|V?I{0,3}[\.])";
If you have a hard time identifying the wanted groups in the result you can name them as specified in the php.net documentation.
That would look something like this:
$pattern = "(?P<groupname>IX|IV|V?I{0,3}[\.])";
You get 0-indexed for all mathced string and result for every paretness (). it's helpful to get groups i.e
preg_match('~([0-9]+)([a-z]+)','12abc',$x);
$x is ([0]=>12abc [1]=>12 [2]=>abc)
In your case you can simply delete () (1 pair ot them, 1 pair is used as delimiters)

Categories