Display all matches from preg match - php

How can display all the results instead of just the first match from the preg match?
This is the content of $show:
One
Two
Three
This is the PHP code:
preg_match("/<a href=\"(.+?)\">(.+?)<\/a>/", $show, $display);
$xml = "<name>".$display[2]."</name><link>".$display[1]."</link>";
echo $xml;
The output is:
<name>One</name><link>http://website.com/one</link>
But I want it to display all the results like this:
<name>One</name><link>http://website.com/one</link>
<name>Two</name><link>http://website.com/two</link>
<name>Three</name><link>http://website.com/three</link>
this is the output of print_r($display); ...
Array
(
[0] => Array
(
[0] => One
[1] => Two
[2] => Three
)
[1] => Array
(
[0] => http://website.com/one
[1] => http://website.com/two
[2] => http://website.com/three
)
[2] => Array
(
[0] => One
[1] => Two
[2] => Three
)
)

You would use preg_match_all() to get all matches and then iterate through them:
preg_match_all('~(.+?)~s', $html, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
echo "<name>".$m[2]."</name><link>".$m[1]."</link>\n";
}
But I'd recommend using DOM for this task instead.
$doc = new DOMDocument;
$doc->loadHTML($html); // load the HTML data
foreach ($doc->getElementsByTagName('a') as $link) {
echo "<name>".$link->nodeValue."</name><link>".$link->getAttribute('href')."</link>\n";
}
eval.in

you can something like this
$xml = '';
$show = 'One
Two
Three';
preg_match_all("/<a href=\"(.+?)\">(.+?)<\/a>/", $show, $display);
for($i=0; $i<count($display[0]); $i++){
$xml .= "<name>".$display[2][$i]."</name><link>".$display[1][$i]."</link>";
}
echo $xml;
and this will output
<name>One</name><link>http://website.com/one</link><name>Two</name><link>http://website.com/two</link><name>Three</name><link>http://website.com/three</link>
DEMO

Related

PHP extract html tag value into array from string

I'm trying to extract value of each html tag from my string into array. This is my str value:
str = '<li>name1</li><li>name2</li><li>name3</li>'
I want to extract each name (name1, name2, name3) and put it into array. So the output should be:
output = Array(
[0] => 'name1',
[1] => 'name2',
[2] => 'name3'
)
I was looking for some function that may do something similar, but no luck at all :/
You can use html parser for that
$dom = new DomDocument();
$dom->loadHTML($str);
$lis = [];
foreach($dom->getElementsByTagName('li') as $li) {
$lis[] = $li->nodeValue;
}
print_r($lis); // Array ( [0] => name1 [1] => name2 [2] => name3 )
There are multiple ways to do it and regex is one of them. You can try like this way with preg_match_all()
<?php
$re = '/<a ?.*?>([^<]+)<\/a>/m';
$str = '<li>name1</li><li>name2</li><li>name3</li>';
$result = [];
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
// Print the entire match result
foreach($matches as $match){
$result[] = $match[1];
}
print '<pre>';
print_r($result);
Output:
Array (
[0] => name1
[1] => name2
[2] => name3
)
DEMO: https://3v4l.org/B7k58
REGEX: https://regex101.com/r/HPDhtA/1
Actually #splash58 answer is in right direction but he might miss the actual requirement i.e. only Name value not links, if I'm not wrong.
So just try this
$dom = new DomDocument();
$dom->loadHTML($str);
$names = [];
foreach($dom->getElementsByTagName('a') as $a) {
$names[] = $a->nodeValue;
}
print_r($names);
You could also make use of an xpath expression using DOMXPath and specify exactly what you want to find:
//li/a
For example:
$str = '<li>name1</li><li>name2</li><li>name3</li>';
$dom = new DomDocument();
$dom->loadHTML($str);
$xpath = new DOMXPath($dom);
$result = [];
foreach($xpath->evaluate('//li/a') as $a) {
$result[] = $a->nodeValue;
}
print_r($result);
Result
Array
(
[0] => name1
[1] => name2
[2] => name3
)

PHP Check string contain #(any) [duplicate]

I have a string that has hash tags in it and I'm trying to pull the tags out I think i'm pretty close but getting a multi-dimensional array with the same results
$string = "this is #a string with #some sweet #hash tags";
preg_match_all('/(?!\b)(#\w+\b)/',$string,$matches);
print_r($matches);
which yields
Array (
[0] => Array (
[0] => "#a"
[1] => "#some"
[2] => "#hash"
)
[1] => Array (
[0] => "#a"
[1] => "#some"
[2] => "#hash"
)
)
I just want one array with each word beginning with a hash tag.
this can be done by the /(?<!\w)#\w+/ regx it will work
That's what preg_match_all does. You always get a multidimensional array. [0] is the complete match and [1] the first capture groups result list.
Just access $matches[1] for the desired strings. (Your dump with the depicted extraneous Array ( [0] => Array ( [0] was incorrect. You get one subarray level.)
I think this function will help you:
echo get_hashtags($string);
function get_hashtags($string, $str = 1) {
preg_match_all('/#(\w+)/',$string,$matches);
$i = 0;
if ($str) {
foreach ($matches[1] as $match) {
$count = count($matches[1]);
$keywords .= "$match";
$i++;
if ($count > $i) $keywords .= ", ";
}
} else {
foreach ($matches[1] as $match) {
$keyword[] = $match;
}
$keywords = $keyword;
}
return $keywords;
}
Try:
$string = "this is #a string with #some sweet #hash tags";
preg_match_all('/(?<!\w)#\S+/', $string, $matches);
print_r($matches[0]);
echo("<br><br>");
// Output: Array ( [0] => #a [1] => #some [2] => #hash )

PHP Get all Urls from string

So I'm trying to get all the urls from a string with a script that looks like this:
$file = file_get_contents('something.txt');
function getUrls($string) {
preg_match_all('~href=("|\')(.*?)\1~', $string, $out);
print_r($out);
}
getUrls($file);
The urls contained in this document may be imperfect - i.e. "/blah/blah.asp?2". The problem is that when I run this script, I get an array that looks something like this:
Array
(
[0] => Array
(
[0] => href="#A"
[1] => href="#B"
[2] => href="#C"
)
[1] => Array
(
[0] => "
[1] => "
[2] => "
)
[2] => Array
(
[0] => #A
[1] => #B
[2] => #C
)
)
Any idea what could be going on here? I have no idea why it is returning alphabetical lists with hash signs instead of the desired urls. How can I go about just returning the urls?
The way of evil:
$file = file_get_contents('something.txt');
function displayUrls($string) {
$pattern = '~\bhref\s*+=\s*+["\']?+\K(?!#)[^\s"\'>]++~';
preg_match_all($pattern, $string, $out);
print_r($out[0]);
}
displayUrls($file);
The good way:
$doc = new DOMDocument();
#$doc->loadHTMLFile('something.txt');
$links = $doc->getElementsByTagName('a');
foreach($links as $link) {
$href = $link->getAttribute('href');
if ($href[0] != '#') $result[] = $href;
}
print_r($result);

Split string between less and greater than

I need to split this kind of strings to separate the email between less and greater than < >. Im trying with the next regex and preg_split, but I does not works.
"email1#domain.com" <email1#domain.com>
News <news#e.domain.com>
Some Stuff <email-noreply#somestuff.com>
The expected result will be:
Array
(
[0] => "email1#domain.com"
[1] => email#email.com
)
Array
(
[0] => News
[1] => news#e.domain.com
)
Array
(
[0] => Some Stuff
[1] => email-noreply#somestuff.com
)
Code that I am using now:
foreach ($emails as $email)
{
$pattern = '/<(.*?)>/';
$result = preg_split($pattern, $email);
print_r($result);
}
You may use some of the flags available for preg_split: PREG_SPLIT_DELIM_CAPTURE and PREG_SPLIT_NO_EMPTY.
$emails = array('"email1#domain.com" <email1#domain.com>', 'News <news#e.domain.com>', 'Some Stuff <email-noreply#somestuff.com>');
foreach ($emails as $email)
{
$pattern = '/<(.*?)>/';
$result = preg_split($pattern, $email, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
print_r($result);
}
This outputs what you expect:
Array
(
[0] => "email1#domain.com"
[1] => email1#domain.com
)
Array
(
[0] => News
[1] => news#e.domain.com
)
Array
(
[0] => Some Stuff
[1] => email-noreply#somestuff.com
)
Splitting on something removes the delimiter (i.e. everything the regex matches). You probably want to split on
\s*<|>
instead. Or you can use preg_match with the regex
^(.*?)\s*<([^>]+)>
and use the first and second capturing groups.
This will do the job. click here for Codepad link
$header = '"email1#domain.com" <email1#domain.com>
News <news#e.domain.com>
Some Stuff <email-noreply#somestuff.com>';
$result = array();
preg_match_all('!(.*?)\s+<\s*(.*?)\s*>!', $header, $result);
$formatted = array();
for ($i=0; $i<count($result[0]); $i++) {
$formatted[] = array(
'name' => $result[1][$i],
'email' => $result[2][$i],
);
}
print_r($formatted);
preg_match_all("/<(.*?)>/", $string, $result_array);
print_r($result_array);
$email='"email1#domain.com" <email1#domain.com>
News <news#e.domain.com>
Some Stuff <email-noreply#somestuff.com>';
$pattern = '![^\>\<]+!';
preg_match_all($pattern, $email,$match);
print_r($match);
Ouput:
Array ( [0] => Array (
[0] => "email1#domain.com"
[1] => email1#domain.com
[2] => News
[3] => news#e.domain.com
[4] => Some Stuff
[5] => email-noreply#somestuff.com ) )
You can also split by <, and get rid of ">" in $result
$pattern = '/</';
$result = preg_split($pattern, $email);
$result = preg_replace("/>/", "", $result);

Specifying object in PHP Array from JSON

I'm trying to use a specific object type from a JSON feed, and am having a hard time specifying it. Using the code below I grab and print the specific array (max) I want,
$jsonurl = "LINK";
$json = file_get_contents($jsonurl,0,null,null);
$json_output = json_decode($json,true);
$max_output = $json_output["max"];
echo '<pre>';
print_r($max_output);
echo '</pre>';
And from the Array below, all I want to work with is the [1] objects in each array. How can I specify and get just those values?
Array
(
[0] => Array
(
[0] => 1309924800000
[1] => 28877
)
[1] => Array
(
[0] => 1310011200000
[1] => 29807
)
[2] => Array
(
[0] => 1310097600000
[1] => 33345
)
[3] => Array
(
[0] => 1310184000000
[1] => 33345
)
[4] => Array
(
[0] => 1310270400000
[1] => 33345
)
[5] => Array
(
[0] => 1310356800000
[1] => 40703
)
Well you could fetch those values with array_map:
$max_output = array_map(function($val) { return $val[1]; }, $json_output["max"]);
This requires PHP 5.3, if you use an earlier version, then you can use create_function to achieve similar results:
$max_output = array_map(create_function('$val', 'return $val[1];'), $json_output["max"]);
When you need to create new array which will contain only second values, you may use either foreach loop which will create it or use array_map() (just for fun with anonymous function available since php 5.3.0):
$newArray = array_map( function( $item){
return $item[1]
},$array);
Then you want to use last ("max" -> considering array with numeric keys) item, you can use end():
return end( $item);
And when you can process your data sequentially (eg. it's not part of some big getData() function) you can rather use foreach:
foreach( $items as $key => $val){
echo $val[1] . " is my number\n";
}
After you get $max_output...
for( $i = 0; $i < length( $max_output ); $i++ ) {
$max_output[$i] = $max_output[$i][1];
}
try this:
$ones = array();
foreach ($max_output as $r)
$ones[] = $r[1];

Categories