I need to extract a variable based on a portion of a string. the string corresponds to a third level domain name, as in the example below.
$variable1 = "subdomain1.domain24.com"
$variable2 = "subdomain2.newdomain24.com"
I have to extract from the domain (therefore excluding the subdomain) the tld and the number 24. All domains ends with "24.com"
so result must be:
for variable1 : domain
for variable2 : newdomain
Regular expressions is one way for this kind of task
the domain must follow a dot
24\.com$ is saying match 24.com at the end of the string
https://www.php.net/manual/en/function.preg-match.php
preg_match('/\.(?<domain>[^\.]+)24\.com$/', 'subdomain2.newdomain24.com', $matches );
var_dump($matches);
// array(3) {
// [0]=> string(16) ".newdomain24.com"
// ["domain"]=> string(9) "newdomain"
// [1]=> string(9) "newdomain"
// }
Explode your string on . and remove 2 last characters (as it always 24):
$urls = [
"subdomain1.domain24.com",
"subdomain2.newdomain24.com",
];
foreach ($urls as $url) {
$parts = explode('.', $url);
$domain = substr($parts[1], 0, -2);
var_dump($domain);
}
Example
Related
I'm working with a string containing parameters, separated by some special characters in PHP with preg_match
An example could be like this one, which has four parameters.
1stparm?#?1111?#?2ndParm?#?2222?#?3rdParm?#?3333?#?4thparm?#?444?#?
Each parameter name is followed by ?#?, and its value is right next to it, ending with ?#? (note: values can be strings or numbers, and even special characters)
I've probably overcomplicated my regex, which works in SOME cases, but not if I search for the last parameter in the string..
This example returns 2222 as the correct value (in group 1) for 2ndParm
(?:.*)2ndParm\?#\?(.*?)\?#\?(?=.)(.*)
but it fails if 2ndParm is the last one in the string as in the following example:
1stparm?#?1111?#?2ndParm?#?2222?#?
I'd also appreciate help in just returning one group with my result.. i havent been able to do so, but since I always get the one I'm interested in group 1, I can get it easily anyway.
Without regex:
$str ='1stparm?#?1111?#?2ndParm?#?2222?#?3rdParm?#?3333?#?4thparm?#?444?#?';
$keyval = explode('?#?', trim($str, '?#'));
$result = [];
foreach($keyval as $item) {
[$key, $result[$key]] = explode('?#?', $item);
}
print_r($result);
demo
You don't need to use a regex for everything, and you should have a serious talk with whoever invented this horrid format about the fact that JSON, YAML, TOML, XML, etc exist.
function bizarre_unserialize($in) {
$tmp = explode('?#?', $in);
$tmp = array_filter($tmp); // remove empty
$tmp = array_map(
function($a) { return explode('?#?', $a); },
$tmp
);
// rearrange to key-value
return array_combine(array_column($tmp, 0), array_column($tmp, 1));
}
$input = '1stparm?#?1111?#?2ndParm?#?2222?#?3rdParm?#?3333?#?4thparm?#?444?#?';
var_dump(
bizarre_unserialize($input)
);
Output:
array(4) {
["1stparm"]=>
string(4) "1111"
["2ndParm"]=>
string(4) "2222"
["3rdParm"]=>
string(4) "3333"
["4thparm"]=>
string(3) "444"
}
You can use
(?P<key>.+?)
\Q?#?\E
(?P<value>.+?)
\Q?#?\E
in verbose mode, see a demo on regex101.com.
The \Q...\E construct disables the ? and # "super-powers" (no need to escape them here).
In PHP this could be
<?php
$string = "1stparm?#?1111?#?2ndParm?#?2222?#?3rdParm?#?3333?#?4thparm?#?444?#?";
$regex = "~(?P<key>.+?)\Q?#?\E(?P<value>.+?)\Q?#?\E~";
preg_match_all($regex, $string, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
echo $match["key"] . " = " . $match["value"] . "\n";
}
?>
Which yields
1stparm = 1111
2ndParm = 2222
3rdParm = 3333
4thparm = 444
Or shorter:
$result = array_map(
function($x) {return array($x["key"] => $x["value"]);}, $matches);
print_r($result);
I want to grab a text with PHP just like for an example, There is a data "The apple=10" and I want to grab only the numbers from the data which looks exactly like that. I mean, the number's place would be after 'equals'.
and my problem is that the number from the source can be 2 or 3 characters or on the other word it is inconstant.
please help me to solve them :)
$string = "Apple=10 | Orange=3 | Banana=7";
$elements = explode("|", $string);
$values = array();
foreach($elements as $element)
{
$element = trim($element);
$val_array = explode("=", $element);
$values[$val_array[0]] = $val_array[1];
}
var_dump($values);
Output:
array(3) {
["Apple"]=> string(2) "10"
["Orange"]=> string(1) "3"
["Banana"]=> string(1) "7"
}
Hope thats how you need it :)
Well, php is a bit lazy about int conversion, so 12345blablabla can be converted to 12345:
$value = intval(substr($str, strpos($str, '=') + 1));
Of course, this is not the cleanest way but it is simple. If you want something cleaner, you could use a regexp:
preg_match ('#=([0-9]+)#', $str, $matches);
$value = intval($matches[1]) ;
Try the below code:
$givenString= "The apple=10";
$required_string = substr($givenString, strpos($givenString, "=") + 1);
echo "output = ".$required_string ; // output = 10
Using strpos() function, you can Find the position of the first occurrence of a substring in a string
and substr() function, Return part of a string.
I have a string comma separated where I want to get 2 values in variables. How can I accomplish it.
$responseData = "Data: invoice=1216,card=AMEX";
I am looking for value of Invoice and Card.
I tried using instring but not getting value I want.
sscanf()
You can use sscanf() to achieve this result.
sscanf() takes the same format as printf(), allowing you to provide a variable and expected format string, and will return the matching results.
For example:
list($invoice, $card) = sscanf($responseData, "Data: invoice=%d,card=%s");
var_dump($invoice); // int(1216)
var_dump($card); // string(4) "AMEX"
Community wiki of Mark Baker's answer in the comments above.
explode()
You can also do this manually by breaking up the string by delimiters with explode(). The Data: component is irrelevant, so trim it off, then split by commas, then split by = to get a key => value pair.
For example:
// Remove the Data: component
$responseData = ltrim($responseData, 'Data: ');
$example = array();
// Split by commas
foreach (explode(',', $responseData) as $value) {
// Split by equals
list ($k, $v) = explode('=', $value);
$example[$k] = $v;
}
var_dump($example);
// array(2) {
// ["invoice"]=>
// string(4) "1216"
// ["card"]=>
// string(4) "AMEX"
// }
preg_match()
Here is the preg_match version using named subpatterns:
$subject = 'Data: invoice=1216,card=AMEX';
$matches = [];
preg_match('/Data: invoice=(?<invoice>\d+),card=(?<card>\w+)/', $subject, $matches);
var_dump($matches['invoice']); // string(4) "1216"
var_dump($matches['card']); // string(4) "AMEX"
I want to replace (well, alter) all youtube links from the text block that don't have query string with manual query string.
For example, text code could look like this:
http://youtube.com/embed/ABC
http://youtube.com/embed/DEF?foo=bar
http://youtube.com/embed/EFG
And I want it to look like:
http://youtube.com/embed/ABC?sup=bro
http://youtube.com/embed/DEF?foo=bar
http://youtube.com/embed/EFG?sup=bro
What is the best way of achieving that using PHP?
Simply check if :
there's no ?, with ^([^?]+)$
the query string is empty, with \?$
$links = array(
'http://youtube.com/embed/ABC',
'http://youtube.com/embed/DEF?foo=bar',
'http://youtube.com/embed/EFG',
'http://youtube.com/embed/HIJ?',
);
$nlinks = preg_replace('/^([^?]+)$|\?$/', '$1?sup=bro', $links);
var_dump($nlinks);
/*
* array(3) {
* [0]=> string(36) "http://youtube.com/embed/ABC?sup=bro"
* [1]=> string(36) "http://youtube.com/embed/DEF?foo=bar"
* [2]=> string(36) "http://youtube.com/embed/EFG?sup=bro"
* [2]=> string(36) "http://youtube.com/embed/HIJ?sup=bro"
* }
*/
EDIT
I added a case for urls with empty query string, like http://youtube.com/embed/HIJ?
A solution without regex. Get all the URLs into an array, use parse_url() to grab the query string part (if there exists one) and append the custom $query inside the loop.
$query = 'sup=bro'; // define this
foreach($urls as &$url) {
$parts = parse_url($url);
if (!isset($parts['query'])) {
$url .= '?' . $query;
}
}
print_r($urls);
Output:
Array
(
[0] => http://youtube.com/embed/ABC?sup=bro
[1] => http://youtube.com/embed/DEF?foo=bar
[2] => http://youtube.com/embed/EFG?sup=bro
)
Demo.
I think that you need check strings using preg_match. If you have remainder after "?", leave it as is; otherwise, add "sup=bro".
You can use this pattern:
$urls = <<<LOD
http://youtube.com/embed/ABC
http://youtube.com/embed/DEF?foo=bar
http://youtube.com/embed/EFG
LOD;
$urls = preg_replace('~/[^/?\s]*\K$~m', '?sup=bro', $urls);
Could someone tell me how I would do this. I have 3 strings.
$route = '/user/$1/profile/$2';
$path = '/user/profile/$1/$2';
$url = '/user/jason/profile/friends';
What I need to do is check to see if the url conforms to the route. I am trying to do this as follows.
$route_segments = explode('/', $route);
$url_segments = explode('/', $url);
$count = count($url_segments);
for($i=0; $i < $count; $i++) {
if ($route_segments[$i] != $url_segments[$i] && ! preg_match('/\$[0-9]/', $route_segments[$i])) {
return false;
}
}
I assume the regex works, it's the first I have ever written by myself. :D
This is where I am stuck. How do I compare the following strings:
$route = '/user/$1/profile/$2';
$url = '/user/jason/profile/friends';
So I end up with:
array (
'$1' => 'jason',
'$2' => 'friends'
);
I assume that with this array I could then str_replace these values into the $path variable?
$route_segments = explode('/',$route);
$url_segments = explode('/',$url);
$combined_segments = array_combine($route_segments,$url_segments);
Untested and not sure how it reacts with unequal array lengths, but that's probably what you're looking for regarding an element-to-element match. Then you can pretty much iterate the array and look for $ and use the other value to replace it.
EDIT
/^\x24[0-9]+$/
Close on the RegEx except you need to "Escape" the $ in a regex because this is a flag for end of string (thus the \x24). The [0-9]+ is a match for 1+ number(s). The ^ means match to the beginning of the string, and, as explained, the $ means match to the end. This will insure it's always a dollar sign then a number.
(actually, netcoder has a nice solution)
I did something similar in a small framework of my own.
My solution was to transform the template URL: /user/$1/profile/$2
into a regexp capable of parsing parameters: ^\/user\/([^/]*)/profile/([^/]*)\/$
I then check if the regexp matches or not.
You can have a look at my controller code if you need to.
You could do this:
$route = '/user/$1/profile/$2';
$path = '/user/profile/$1/$2';
$url = '/user/jason/profile/friends';
$regex_route = '#'.preg_replace('/\$[0-9]+/', '([^/]*)', $route).'#';
if (preg_match($regex_route, $url, $matches)) {
$real_path = $path;
for ($i=1; $i<count($matches); $i++) {
$real_path = str_replace('$'.$i, $matches[$i], $real_path);
}
echo $real_path; // outputs /user/profile/jason/friends
} else {
// route does not match
}
You could replace any occurrence of $n by a named group with the same number (?P<_n>[^/]+) and then use it as pattern for preg_match:
$route = '/user/$1/profile/$2';
$path = '/user/profile/$1/$2';
$url = '/user/jason/profile/friends';
$pattern = '~^' . preg_replace('/\\\\\$([1-9]\d*)/', '(?P<_$1>[^/]+)', preg_quote($route, '~')) . '$~';
if (preg_match($pattern, $url, $match)) {
var_dump($match);
}
This prints in this case:
array(5) {
[0]=>
string(28) "/user/jason/profile/friends"
["_1"]=>
string(5) "jason"
[1]=>
string(5) "jason"
["_2"]=>
string(7) "friends"
[2]=>
string(7) "friends"
}
Using a regular expression allows you to use the wildcards at any position in the path and not just as a separate path segment (e.g. /~$1/ for /~jason/ would work too). And named subpatterns allows you to use an arbitrary order (e.g. /$2/$1/ works as well).
And for a quick fail you can additionally use the atomic grouping syntax (?>…).