sn00pers Posted January 27, 2016 Share Posted January 27, 2016 Hi! I am trying to figure out how I can split a string based on the last of several instances of a character that exists within a string and return just the two parts. For example: netstat displays IPv6 addresses with the port number attached via a colon. But the colon is also used for the hextets in the address. 2001:db8:a0b:12f0::1:25 While this IP/Port have many colons, I am trying to split by the very last one to get the results: 2001:db8:a0b:12f0::1 25 This doesn't seem like it should be difficult, but yet I am struggling to get it to work with various combinations of preg_split or strrchr. Can annyone offer any advice? I have a feeling the answer is going to make me go "duh, of course!" Quote Link to comment Share on other sites More sharing options...
requinix Posted January 27, 2016 Share Posted January 27, 2016 Not being able to think of any nicer solution, I'd go with substr() and strrpos(). $ipport = "2001:db8:a0b:12f0::1:25"; $p = strrpos($ipport, ":"); $ip = substr($ipport, 0, $p); $port = substr($ipport, $p + 1); 1 Quote Link to comment Share on other sites More sharing options...
Barand Posted January 27, 2016 Share Posted January 27, 2016 Or strrchr $ipport = "2001:db8:a0b:12f0::1:25"; $end = strrchr($ipport, ':'); echo $end; //--> :25 Quote Link to comment Share on other sites More sharing options...
QuickOldCar Posted January 27, 2016 Share Posted January 27, 2016 To expand onto Barand's to get first part back minus port. $ipport = "2001:db8:a0b:12f0::1:25"; $end = strrchr($ipport, ':'); $first = substr($ipport, 0, -strlen($end)); echo $first; //2001:db8:a0b:12f0::1 echo $end; //--> :25 Quote Link to comment Share on other sites More sharing options...
sn00pers Posted January 27, 2016 Author Share Posted January 27, 2016 (edited) Thank you so much. I hadn't thought about doing it in two steps (one for first part, one for second part). Makes sense!EDIT: I had the browser window open over night and did not refresh it to see there were additional responses since requinix. So thank you everyone who responded. Edited January 27, 2016 by sn00pers Quote Link to comment Share on other sites More sharing options...
ginerjm Posted January 27, 2016 Share Posted January 27, 2016 $split_chr = ':'; $parts = explode($split_chr,$source); $sz = count($parts) -1; $part1 = ''; for ($i=0; $i<$sz-1; $i++) $part1 .= $parts[$i]; $part2 = $parts[$sz]; Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 27, 2016 Share Posted January 27, 2016 (edited) $split_chr = ':'; $parts = explode($split_chr,$source); $sz = count($parts) -1; $part1 = ''; for ($i=0; $i<$sz-1; $i++) $part1 .= $parts[$i]; $part2 = $parts[$sz]; If you're going to use explode, then might as well use pop() to remove the last element and implode() the remaining elements back together $split_chr = ':'; $parts = explode($split_chr, $source); $last = pop($parts); $first = implode(':', $parts); Edited January 27, 2016 by Psycho Quote Link to comment Share on other sites More sharing options...
ginerjm Posted January 27, 2016 Share Posted January 27, 2016 Hmmm, I must not understand the question. OP wanted two parts - one with the first n pieces and one with just the last piece. That seems to be what his/her example shows. Using the implode to build the first part is a good idea, but you have lost the last part. Quote Link to comment Share on other sites More sharing options...
sn00pers Posted January 27, 2016 Author Share Posted January 27, 2016 (edited) Sorry if I was confusing. I was looking to end up with two strings. The IP, and the Port. I just had to add a little tweak to remove the colon from the port number, but all is working. Edited January 27, 2016 by sn00pers Quote Link to comment Share on other sites More sharing options...
requinix Posted January 27, 2016 Share Posted January 27, 2016 Here's a quick one: preg_match('/^(.*)\d+)$/', "2001:db8:a0b:12f0::1:25", $match) && list(, $ip, $port) = $match;(I was deliberately avoiding doing this with my first answer) Quote Link to comment Share on other sites More sharing options...
ginerjm Posted January 27, 2016 Share Posted January 27, 2016 I think I gave you that solution. Perhaps a little unwieldly, but correct. Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 28, 2016 Share Posted January 28, 2016 (edited) Hmmm, I must not understand the question. OP wanted two parts - one with the first n pieces and one with just the last piece. That seems to be what his/her example shows. Using the implode to build the first part is a good idea, but you have lost the last part. I only lost the last part because I used pop() instead of the correct nomenclature of array_pop(). Other than that, the code retrieves both parts $source = "2001:db8:a0b:12f0::1:25"; $split_chr = ':'; $parts = explode($split_chr, $source); $last = array_pop($parts); $first = implode(':', $parts); echo "First: {$first}<br>\n"; echo "Last: {$last}<br>\n"; First: 2001:db8:a0b:12f0::1Last: 25 Edited January 28, 2016 by Psycho Quote Link to comment Share on other sites More sharing options...
sn00pers Posted January 28, 2016 Author Share Posted January 28, 2016 Here's a quick one: preg_match('/^(.*)\d+)$/', "2001:db8:a0b:12f0::1:25", $match) && list(, $ip, $port) = $match;(I was deliberately avoiding doing this with my first answer) I think I used that regex before I posted this thread, but was trying a preg_split with it so that might be why I wasn't able to get it to work. I often use preg_match and then an additional line to get a string from the output array. What you did here looked really interesting. How does the and part work here? I like that it's one line because it makes it clear that it's all part of the same operation. Quote Link to comment Share on other sites More sharing options...
requinix Posted January 28, 2016 Share Posted January 28, 2016 What you did here looked really interesting. How does the and part work here? I like that it's one line because it makes it clear that it's all part of the same operation.Don't use it as a matter of practice. It's just a clever way of doing two commands at once; if the regex failed then $ip and $port would be undefined. You know $x && $y? $y doesn't get evaluated unless $x is true, and if $x is false then it does not. And since preg_match() returns 1 (which is "true") if it matches, the assignment only gets evaluated if the regex matched. Quote Link to comment Share on other sites More sharing options...
sn00pers Posted January 28, 2016 Author Share Posted January 28, 2016 Thanks for the explanation. I haven't used really used $x && $y types of evaluations before so now I need to start thinking about where I can incorporate that. Quote Link to comment Share on other sites More sharing options...
requinix Posted January 28, 2016 Share Posted January 28, 2016 I haven't used really used $x && $y types of evaluations before so now I need to start thinking about where I can incorporate that.Please don't. You'll encourage me to never post stuff like that again. I only ever use it with really, really simple stuff. Like $variable && function_call($variable);or isset($array["value"]) && $obj->property = $array["value"];You can see what it's doing at a quick glance. No thinking involved. That thing with the regex and the list() is too complicated: you have to think "okay, what is preg_match() returning and what are the values in $match and why is list() skipping the first array value" and it's just a hassle. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.