Let's say I have a URL: https://somesite.com/0/posts/20/290/755653-Title.html How would I get these variables: /0/, /20/, /290/ ? Note they are variables, they will always be different.
I thought I could get them like so:
$url = '//somesite.com/0/posts/20/290/755653-Title.html';
var_dump(parse_url($url));
but the array doesn't show them as separate variables. Should it be done with a preg_replace instead? I don't think I know how. Thank you for your help.
One option is to use a positive lookahead with preg_match_all where you capture the pattern in a capturing group:
(?=(/\d+/))
That will match
(?= Positive lookahead, assert what is directly on the right is
(/\d+/) Match /, 1+ digits and /
) Close positive lookahead
Regex demo | Php demo
For example
$re = '~(?=(/\d+/))~m';
$str = 'https://somesite.com/0/posts/20/290/755653-Title.html';
preg_match_all($re, $str, $matches);
print_r($matches[1]);
Result
Array
(
[0] => /0/
[1] => /20/
[2] => /290/
)
If you want to get the digits only without the surrounding slashes you could add the group around the digits only
(?=/(\d+)/)
Php demo
You could use explode() and turn the string into an array divided by the "/" delimiter.
<?php
// Example 1
$url = "https://somesite.com/0/posts/20/290/755653-Title.html";
$pieces = explode("/", $url);
echo $pieces[0] . "<br />";
echo $pieces[1] . "<br />";
echo $pieces[2] . "<br />";
echo $pieces[3] . "<br />";
echo $pieces[4] . "<br />";
echo $pieces[5] . "<br />";
echo $pieces[5] . "<br />";
echo $pieces[6] . "<br />";
echo $pieces[7] . "<br />";
echo "<hr />";
// Example 2
$data = "https://somesite.com/0/posts/20/290/755653-Title.html";
list($first, $second, $third, $fourth, $fifth, $sixth, $seventh, $eighth) = explode("/", $url);
echo $first . "<br />";
echo $second . "<br />";
echo $third . "<br />";
echo $fourth . "<br />";
echo $fifth . "<br />";
echo $sixth . "<br />";
echo $seventh . "<br />";
echo $eighth . "<br />";
?>
Output:
https:
somesite.com
0
posts
20
20
290
755653-Title.html
https:
somesite.com
0
posts
20
290
755653-Title.html
We can try splitting on path separator, and then using array_filter with an inline function to retain only purely numerical components:
$str = 'https://somesite.com/0/posts/20/290/755653-Title.html';
$parts = explode("/", $str);
$parts = array_filter($parts, function($item) { return is_numeric($item); });
print_r($parts);
This prints:
Array
(
[3] => 0
[5] => 20
[6] => 290
)
Note that this approach completely avoids the use of a formal regex, which might have performance implications if you needed to do this often in your script.
Related
My regex strips all points away except the last one. Great!
But what I wish, is only to strip "thousand" separators, not the "float" ones. I suppose floats ends with one or two digits.
I cannot change the input format.
Any idea how to extend that regex?
<?php
print_r(preg_replace('/\.(?=.*\.)/', '', "1.234.20")); // works
echo "<hr />";
print_r(preg_replace('/\.(?=.*\.)/', '', "1234.20")); // works
echo "<hr />";
print_r(preg_replace('/\.(?=.*\.)/', '', "1234.2")); // works
echo "<hr />";
print_r(preg_replace('/\.(?=.*\.)/', '', "1234.217")); // works
echo "<hr />";
print_r(preg_replace('/\.(?=.*\.)/', '', "1.000.234.20")); // works
echo "<hr />";
print_r(preg_replace('/\.(?=.*\.)/', '', "1.234")); // buuuh, 1234 would be correct
?>
If you assume every thousand separator is followed by exactly 3 digits, you can do it this way.
This excludes the case where a float is ending with 3 or more digits...
<?php
print_r(preg_replace('/\.([0-9]{3})/', '$1', "1.234.20")); // 1234.20
echo "<hr />";
print_r(preg_replace('/\.([0-9]{3})/', '$1', "1234.20")); // 1234.20
echo "<hr />";
print_r(preg_replace('/\.([0-9]{3})/', '$1', "1234.2")); // 1234.2
echo "<hr />";
print_r(preg_replace('/\.([0-9]{3})/', '$1', "1234.217")); // 1234217
echo "<hr />";
print_r(preg_replace('/\.([0-9]{3})/', '$1', "1.000.234.20")); // 1000234.20
echo "<hr />";
print_r(preg_replace('/\.([0-9]{3})/', '$1', "1.234")); // 1234
?>
I have this PHP code which I'm trying to extract some information but I stopped to href step:
$site = "http://www.sports-reference.com/olympics/countries";
$site_html = file_get_html($site);
$country_dirty = $site_html->getElementById('div_countries');
foreach($country_dirty->find('img') as $link){
$country = $link->alt;
$link_country = "$site/$country";
$link_country_html = file_get_html($link_country);
$link_season = $link_country_html->getElementById('div_medals');
foreach($link_season->find('a') as $season){
echo $link_year_season = $season->href . "\n";
//echo $link_season = strstr ($link_year_season,'summer') . "\n";
}
}
The variable $link_year_season gets me the following output:
/olympics/countries/AFG/summer/2012/
/olympics/athletes/ba/nesar-ahmad-bahawi-1.html
/olympics/athletes/ni/rohullah-nikpai-1.html
/olympics/countries/AFG/summer/2008/
/olympics/athletes/ba/nesar-ahmad-bahawi-1.html
/olympics/athletes/ni/rohullah-nikpai-1.html
/olympics/countries/AFG/summer/2004/
/olympics/countries/AFG/summer/1996/
/olympics/countries/AFG/summer/1988/
/olympics/countries/AFG/summer/1980/
/olympics/countries/AFG/summer/1972/
.....
I'd like to know if it is possible to get only this output:
/olympics/countries/AFG/summer/2012/
/olympics/countries/AFG/summer/2008/
/olympics/countries/AFG/summer/2004/
/olympics/countries/AFG/summer/1996/
/olympics/countries/AFG/summer/1988/
/olympics/countries/AFG/summer/1980/
/olympics/countries/AFG/summer/1972/
You should be able to use this regex to check that the link starts with /olympics/countries/AFG/summer/ then a number and a /.
foreach($link_season->find('a') as $season){
if(preg_match('~^/olympics/countries/AFG/summer/\d+/~', $season->href)) {
echo $link_year_season = $season->href . "\n";
//echo $link_season = strstr ($link_year_season,'summer') . "\n";
}
}
Demo: https://regex101.com/r/bZ1vP3/1
You could also pull the current year by capturing the number after summer (presuming that is a year, first regex just checks for number this one is stricter)..
foreach($link_season->find('a') as $season){
if(preg_match('~^/olympics/countries/AFG/summer/(\d{4})/~', $season->href, $year)) {
echo $link_year_season = $season->href . "\n";
//echo $link_season = strstr ($link_year_season,'summer') . "\n";
echo 'The year is ' . $year[1] . "\n";
}
}
If the season also can vary you could do (?:summer|winter) which would allow for summer or winter to be the fourth directory.
I want to pull some values out of string (in function)
if(!preg_match('/(.+)\.([0-9]*)x([0-9]*)(w|wr|r)?\.([^\.]+)$/', $filename, $matches))
return false;
$file = $matches[1];
$width = $matches[2];
$height = $matches[3];
$set_watermark_or_nonconstrain = $matches[4]; // that's what I need to fix
$ext = $matches[5];
However, if I set string like {$image[0]->filename|resize:614:300:r} (Smarty), all goes well except that $set_watermark_or_nonconstrain is always 'w'. What do I need to set instead of w|wr|r to pull 'w', 'wr' or 'r' from this submask? Thanks!
Using the string example you have given, the following expression does what you are looking for
$string = '{$image[0]->filename|resize:614:300:r}';
if(preg_match('/\{([^\|]+)\|[^:]+:(\d+):(\d+):([^}]+)/', $string, $m)){
echo 'm1: '.$m[1] ."<br />\n";
echo 'm2: '.$m[2] ."<br />\n";
echo 'm3: '.$m[3] ."<br />\n";
echo 'm4: '.$m[4] ."<br />\n";
}
Which produces the following ouput:
m1: $image[0]->filename
m2: 614
m3: 300
m4: r
$cartArray structure:
Array ( [0] => 1. X => 2. Y [2] => 3. Z [3] => 4. XX [4] => 5. YY [5] => )
$list:
$list = array(
"1.",
"2.",
"3.",
"4.",
"5."
);
Function
function alignNum($cartArray, $list)
{
foreach($cartArray as $cA)
{
echo "<br />" . $cA . "<br /><br />";
foreach($list as $l)
{
echo $l . "<br />";
echo "Type of \$l is " . gettype($l) . " and type of \$cA is " . gettype($cA) . "<br />";
$pos = strpos($cA, $l);
echo "Comparing " . $l . " to " . $cA . "<br />";
if ($pos !== true)
{
echo "<br />" . $l . " was not found in " . $cA . "<br /><br />";
continue;
}
else
{
$post_cA = str_replace("EUR", "EUR</span>", $cA);
$new_cA[] = (str_replace($l, substr($l, 0, -4) . "<span style='float: right>'", $cA)) . $post_cA;
return $new_cA;
}
}
}
}
$new_cart = alignNum($cart, $list);
So, I keep getting my custom debug message: "X was not found in Y". I.e it's not founding it X in ANY of the provided strings.
It's not a question of types either. Both are strings.
Any ideas?
EDIT: Also, note that I've censored some stuff out, since this is business related code.
It is generally a bad idea (unless you are C programmer) to compare numeric and boolean even in
if ($pos != true)
but in
if ($pos !== true)
AFAIK it will NEVER match because the variables are different types
German Arlington is actually right.
Have a look what strpos is returning:
Returns the position of where the needle exists relative to the
beginning of the haystack string (independent of offset). Also note
that string positions start at 0, and not 1.
Returns FALSE if the needle was not found.
with
if ($pos !== true)
you are asking wether strpos returned a boolean true (as you are checking typesafe with !==).
But actually strpos may have found the needle and returned i.e 2 for the position of the first match, but you asked for true.
try to check the other way round:
if (false === $pos) { // your debug message }
I am currently using the below code to echo a few different variables and 2 line breaks.
But what I would like to know is how can I echo all of the variables including line breaks into one line of code?
<?php
function findworld($var) {
return strpos($var, "world");
}
$firstvar = "hello world";
$secondvar = findworld($firstvar);
$thirdvar = strlen($firstvar);
echo $firstvar;
echo "<br />";
echo $secondvar;
echo "<br />";
echo $thirdvar;
?>
the concat operator in php is "."
echo $firstvar . "<br />" . $secondvar . "<br />" . $thirdvar;
http://www.php.net/manual/en/language.operators.string.php
You can pass multiple parameters to echo, separated by a comma:
echo $firstvar, "<br />", $secondvar, "<br />", $thirdvar;
To avoid repeating the line break, you could also use implode:
$firstvar = "hello world";
$values = array($firstvar,
findworld($firstvar),
strlen($firstvar));
echo implode('<br />', $values);
You can use string concatenation:
echo $firstvar . "<br />" . $secondvar . "<br />" . $thirdvar;
Like others have said, but with speech marks in the all the correct places ;)
echo $firstvar.'<br />'.$secondvar.'<br />'.$thirdvar;
You don't need to concatenate at all with double quotes, you can just:
echo "$firstvar<br />$secondvar<br />$thirdvar";