Removing first part of string? - php

Trying to edit urls in array.
[0] => https://www.proud-web.jp/mansion/b115110/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011244
[1] => https://www.proud-web.jp/mansion/p-ebisuminami88/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011205
As you see urls are like this. trying to remove first url and contain the second.
expected result is like:
https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011244
https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011205
what I tried is right below. In that way I can only remove the second. But how can I fix this code to remove first url in the string not the second.
$result = [];
foreach($setLinks as $key) {
array_push($result, current(explode("/h", $key)));
}

You can use foreach followed by explode to get split the string w.r.t /https. Below is the code:
$array = ['https://www.proud-web.jp/mansion/b115110/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011244','https://www.proud-web.jp/mansion/p-ebisuminami88/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011205'];
$result = [];
foreach($array as $arr){
$getUrl = explode('/https', $arr);
array_push($result, 'https' . $getUrl[1]);
}
print_r($result);

I would separate the task in 3 subtasks.
First one being to capture the protocol using regex in example (the protocol of that url could be https, http, ftp ...)
Then, capture the url itself, splitting the string using :// as delimiter
Finally, rebuild protocol . "://" . url
In example :
<?php
$array =
[
'https://www.proud-web.jp/mansion/b115110/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011244',
'https://www.proud-web.jp/mansion/p-ebisuminami88/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011205',
'http://www.example.com/home/http://something',
'http://www.example.com/https/ftp://something',
'https://nothing.to.capture'
];
$result = array();
/*
* matches a slash -> \/
* followed by letters -> ([a-z]*)
* followed by :// -> :\/\/
* and capture the letters -> (the parenthesis)
* it can match, in example : something/mycustomprotocol://somethingelse
*/
$pattern = "/\/([a-z]*):\/\//i";
foreach($array as $item) {
preg_match_all($pattern, $item, $matches);
if (count($matches) > 0)
{
$urls = explode("://", $item, 3);
if (count($urls) > 2)
{
$protocol = $matches[1][0];
$result[] = $protocol . "://" . $urls[2];
}
}
}
var_dump($result);
Output
array(4) {
[0]=>
string(83) "https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011244"
[1]=>
string(83) "https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011205"
[2]=>
string(16) "http://something"
[3]=>
string(15) "ftp://something"
}

try this
unset($setLinks[0]);
foreach($setLinks as $key) {
echo $key;
}

This is what I would do:
$urls = [
'https://www.proud-web.jp/mansion/b115110/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011244',
'https://www.proud-web.jp/mansion/p-ebisuminami88/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011205'
];
foreach($urls as &$url){
$url = 'http'.preg_split('/^.+?\/http/', $url, 2, PREG_SPLIT_NO_EMPTY)[0];
}
print_r($urls);
Output
Array
(
[0] => https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011244
[1] => https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011205
)
Sandbox
I set it up so that it would handle both HTTP and HTTPS

You could use preg_replace to remove the leading text:
foreach ($setLinks as &$value) {
$value = preg_replace('#^.+(https?://.*)$#', '$1', $value);
}
print_r($setLinks);
Output:
Array (
[0] => https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011244
[1] => https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011205
)
Demo on 3v4l.org

i miss understand your question .kindly try it
<?php $quest = array("https://www.proud-web.jp/mansion/b115110/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011244",
"https://www.proud-web.jp/mansion/p-ebisuminami88/https://www.proud-web.jp/module/structure/outline/BukkenOutline.xphp?code_no=011205");
foreach($quest as $q )
{
$allquest = explode("/https",$q);
echo "https".$allquest[1];
}
?>

Related

PHP: String to multidimensional array

(Sorry for my bad English)
I have a string that I want to split into an array.
The corner brackets are multiple nested arrays.
Escaped characters should be preserved.
This is a sample string:
$string = '[[["Hello, \"how\" are you?","Good!",,,123]],,"ok"]'
The result structure should look like this:
array (
0 =>
array (
0 =>
array (
0 => 'Hello, \"how\" are you?',
1 => 'Good!',
2 => '',
3 => '',
4 => '123',
),
),
1 => '',
2 => 'ok',
)
I have tested it with:
$pattern = '/[^"\\]*(?:\\.[^"\\]*)*/s';
$return = preg_match_all($pattern, $string, null);
But this did not work properly. I do not understand these RegEx patterns (I found this in another example on this page).
I do not know whether preg_match_all is the correct command.
I hope someone can help me.
Many Thanks!!!
This is a tough one for a regex - but there is a hack answer to your question (apologies in advance).
The string is almost a valid array literal but for the ,,s. You can match those pairs and then convert to ,''s with
/,(?=,)/
Then you can eval that string into the output array you are looking for.
For example:
// input
$str1 = '[[["Hello, \\"how\\" are you?","Good!",,,123]],,"ok"]';
// replace , followed by , with ,'' with a regex
$pattern = '/,(?=,)/';
$replace = ",''";
$str2 = preg_replace($pattern, $replace, $str1);
// eval updated string
$arr = eval("return $str2;");
var_dump($arr);
I get this:
array(3) {
[0]=>
array(1) {
[0]=>
array(5) {
[0]=>
string(21) "Hello, "how" are you?"
[1]=>
string(5) "Good!"
[2]=>
string(0) ""
[3]=>
string(0) ""
[4]=>
int(123)
}
}
[1]=>
string(0) ""
[2]=>
string(2) "ok"
}
Edit
Noting the inherent dangers of eval the better option is to use json_decode with the code above e.g.:
// input
$str1 = '[[["Hello, \\"how\\" are you?","Good!",,,123]],,"ok"]';
// replace , followed by , with ,'' with a regex
$pattern = '/,(?=,)/';
$replace = ',""';
$str2 = preg_replace($pattern, $replace, $str1);
// eval updated string
$arr = json_decode($str2);
var_dump($arr);
If you can edit the code that serializes the data then it's a better idea to let the serialization be handled using json_encode & json_decode. No need to reinvent the wheel on this one.
Nice cat btw.
You might want to use a lexer in combination with a recursive function that actually builds the structure.
For your purpose, the following tokens have been used:
\[ # opening bracket
\] # closing bracket
".+?(?<!\\)" # " to ", making sure it's not escaped
,(?!,) # a comma, not followed by a comma
\d+ # at least one digit
,(?=,) # a comma followed by a comma
The rest is programming logic, see a demo on ideone.com. Inspired by this post.
class Lexer {
protected static $_terminals = array(
'~^(\[)~' => "T_OPEN",
'~^(\])~' => "T_CLOSE",
'~^(".+?(?<!\\\\)")~' => "T_ITEM",
'~^(,)(?!,)~' => "T_SEPARATOR",
'~^(\d+)~' => "T_NUMBER",
'~^(,)(?=,)~' => "T_EMPTY"
);
public static function run($line) {
$tokens = array();
$offset = 0;
while($offset < strlen($line)) {
$result = static::_match($line, $offset);
if($result === false) {
throw new Exception("Unable to parse line " . ($line+1) . ".");
}
$tokens[] = $result;
$offset += strlen($result['match']);
}
return static::_generate($tokens);
}
protected static function _match($line, $offset) {
$string = substr($line, $offset);
foreach(static::$_terminals as $pattern => $name) {
if(preg_match($pattern, $string, $matches)) {
return array(
'match' => $matches[1],
'token' => $name
);
}
}
return false;
}
// a recursive function to actually build the structure
protected static function _generate($arr=array(), $idx=0) {
$output = array();
$current = 0;
for($i=$idx;$i<count($arr);$i++) {
$type = $arr[$i]["token"];
$element = $arr[$i]["match"];
switch ($type) {
case 'T_OPEN':
list($out, $index) = static::_generate($arr, $i+1);
$output[] = $out;
$i = $index;
break;
case 'T_CLOSE':
return array($output, $i);
break;
case 'T_ITEM':
case 'T_NUMBER':
$output[] = $element;
break;
case 'T_EMPTY':
$output[] = "";
break;
}
}
return $output;
}
}
$input = '[[["Hello, \"how\" are you?","Good!",,,123]],,"ok"]';
$items = Lexer::run($input);
print_r($items);
?>

Extracting a string starting with # or # php

function extractConnect($str,$connect_type){
$connect_array = array();
$connect_counter = 0;
$str = trim($str).' ';
for($i =0; $i<strlen($str);$i++) {
$chr = $str[$i];
if($chr==$connect_type){ //$connect_type = '#' or '#' etc
$connectword = getConnect($i,$str);
$connect_array[$connect_counter] = $connectword;
$connect_counter++;
}
}
if(!empty($connect_array)){
return $connect_array;
}
}
function getConnect($tag_index,$str){
$str = trim($str).' ';
for($j = $tag_index; $j<strlen($str);$j++) {
$chr = $str[$j];
if($chr==' '){
$hashword = substr($str,$tag_index+1,$j-$tag_index);
return trim($hashword);
}
}
}
$at = extractConnect("#stackoverflow is great. #google.com is the best search engine","#");
$hash = extractConnect("#stackoverflow is great. #google.com is the best search engine","#");
print_r($at);
print_r($hash);
What this method does is it extracts # or # from a string and return an array of those words.
e.g input #stackoverflow is great. #google.com is the best search engine and outputs this
Array ( [0] => google.com ) Array ( [0] => stackoverflow )
But it seems like this method is to slow is there any alternative ?
You could use a regex to achieve this:
/<char>(\S+)\b/i
Explanation:
/ - starting delimiter
<char> - the character you're searching for (passed as a function argument)
(\S+) - any non-whitespace character, one or more times
\b - word boundary
i - case insensitivity modifier
/ - ending delimiter
Function:
function extractConnect($string, $char) {
$search = preg_quote($char, '/');
if (preg_match('/'.$search.'(\S+)\b/i', $string, $matches)) {
return [$matches[1]]; // Return an array containing the match
}
return false;
}
With your strings, this would produce the following output:
array(1) {
[0]=>
string(10) "google.com"
}
array(1) {
[0]=>
string(13) "stackoverflow"
}
Demo
You can do it like this:
<?php
function extractConnect($strSource, $tags) {
$matches = array();
$tags = str_split($tags);
$strSource = explode(' ', $strSource);
array_walk_recursive($strSource, function(&$item) {
$item = trim($item);
});
foreach ($strSource as $strPart) {
if (in_array($strPart[0], $tags)) {
$matches[$strPart[0]][] = substr($strPart, 1);
}
}
return $matches;
}
var_dump(extractConnect(
"#stackoverflow is great. #twitter is good. #google.com is the best search engine",
"##"
));
Outputs:
This seemed to work for me. Provide it with the symbol you want.
function get_stuff($str) {
$result = array();
$words = explode(' ', $str);
$symbols = array('#', '#');
foreach($words as $word) {
if (in_array($word[0], $symbols)) {
$result[$word[0]][] = substr($word, 1);
}
}
return $result;
}
$str = '#stackoverflow is great. #google.com is the best search engine';
print_r(get_stuff($str));
This outputs Array ( [#] => Array ( [0] => stackoverflow ) [#] => Array ( [0] => google.com ) )

Parsing a string separated by semicolon

How can I parse this string
name:john;phone:12345;website:www.23.com;
into becoming like this
$name = "john";
$phone = "12345"
.....
because I want to save the parameter in one table column, I see joomla using this method to save the menu/article parameter.
Something like this(explode() is the way):
$string = 'name:john;phone:12345;website:www.23.com';
$array = explode(';',$string);
foreach($array as $a){
if(!empty($a)){
$variables = explode(':',$a);
$$variables[0] = $variables[1];
}
}
echo $name;
Working example
Please note: String must be like this, variable_name:value;variable_name2:value and the variable_name or variable cant contain ; or :
Here's how I'd do it:
Use explode() and split the string with ; as the delimiter.
Loop through the result array and explode() by :
Store the second part in a variable and push it into the result array
Optionally, if you want to convert the result array back into a string, you can use implode()
Code:
$str = 'name:john;phone:12345;website:www.23.com;';
$parts = explode(';', $str);
foreach ($parts as $part) {
if(isset($part) && $part != '') {
list($item, $value) = explode(':', $part);
$result[] = $value;
}
}
Output:
Array
(
[0] => john
[1] => 12345
[2] => www.23.com
)
Now, to get these values into variables, you can simply do:
$name = $result[0];
$phone = $result[1];
$website = $result[2];
Demo!
Use explode()
explode — Split a string by string
Description
Returns an array of strings, each of which is a substring of string formed by splitting it on boundaries formed by the string delimiter.
<?php
$string = "name:john;phone:12345;website:www.23.com;";
$pieces = explode(";", $string);
var_dump($pieces);
?>
Output
array(4) {
[0]=>
string(9) "name:john"
[1]=>
string(11) "phone:12345"
[2]=>
string(18) "website:www.23.com"
[3]=>
string(0) ""
}
DEMO
try this
<?php
$str = "name:john;phone:12345;website:www.23.com";
$array=explode(";",$str);
if(count($array)!=0)
{
foreach($array as $value)
{
$data=explode(":",$value);
echo $data[0]." = ".$data[1];
echo "<br>";
}
}
?>

Regex hash and colons

I want to use regular expression to filter substrings from this string
eg: hello world #level:basic #lang:java:php #...
I am trying to produce an array with a structure like this:
Array
(
[0]=> hello world
[1]=> Array
(
[0]=> level
[1]=> basic
)
[2]=> Array
(
[0]=> lang
[1]=> java
[2]=> php
)
)
I have tried preg_match("/(.*)#(.*)[:(.*)]*/", $input_line, $output_array);
and what I have got is:
Array
(
[0] => hello world #level:basic #lang:java:php
[1] => hello world #level:basic
[2] => lang:java:php
)
In this case then I will have to apply this regex few times to the indexes and then apply a regex to filter the colon out. My question is: is it possible to create a better regex to do all in one go? what would the regex be? Thanks
You can use :
$array = explode("#", "hello world #level:basic #lang:java:php");
foreach($array as $k => &$v) {
$v = strpos($v, ":") === false ? $v : explode(":", $v);
}
print_r($array);
do this
$array = array() ;
$text = "hello world #level:basic #lang:java:php";
$array = explode("#", $text);
foreach($array as $i => $value){
$array[$i] = explode(":", trim($value));
}
print_r($array);
Got something for you:
Rules:
a tag begins with #
a tag may not contain whitespace/newline
a tag is preceeded and followed by whitespace or line beginning/ending
a tag can have several parts divided by :
Example:
#this:tag:matches this is some text #a-tag this is no tag: \#escaped
and this one tag#does:not:match
Function:
<?php
function parseTags($string)
{
static $tag_regex = '#(?<=\s|^)#([^\:\s]+)(?:\:([^\s]+))*(?=\s|$)#m';
$results = array();
preg_match_all($tag_regex, $string, $results, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
$tags = array();
foreach($results as $result) {
$tag = array(
'offset' => $result[0][1],
'raw' => $result[0][0],
'length' => strlen($result[0][0]),
0 => $result[1][0]);
if(isset($result[2]))
$tag = array_merge($tag, explode(':', $result[2][0]));
$tag['elements'] = count($tag)-3;
$tags[] = $tag;
}
return $tags;
}
?>
Result:
array(2) {
[0]=>array(7) {
["offset"]=>int(0)
["raw"]=>string(17) "#this:tag:matches"
["length"]=>int(17)
[0]=>string(4) "this"
[1]=>string(3) "tag"
[2]=>string(7) "matches"
["elements"]=>int(3)
}
[1]=>array(5) {
["offset"]=>int(36)
["raw"]=>string(6) "#a-tag"
["length"]=>int(6)
[0]=>string(5) "a-tag"
["elements"]=>int(1)
}
}
Each matched tag contains
the raw tag text
the tag offset and original length (e.g. to replace it in the string later with str... functions)
the number of elements (to safely iterate for($i = 0; $i < $tag['elements']; $i++))
This might work for you:
$results = array() ;
$text = "hello world #level:basic #lang:java:php" ;
$parts = explode("#", $text);
foreach($parts as $part){
$results[] = explode(":", $part);
}
var_dump($results);
Two ways using regex, note that you somehow need explode() since PCRE for PHP doesn't support capturing a subgroup:
$string = 'hello world #level:basic #lang:java:php';
preg_match_all('/(?<=#)[\w:]+/', $string, $m);
foreach($m[0] as $v){
$example1[] = explode(':', $v);
}
print_r($example1);
// This one needs PHP 5.3+
$example2 = array();
preg_replace_callback('/(?<=#)[\w:]+/', function($m)use(&$example2){
$example2[] = explode(':', $m[0]);
}, $string);
print_r($example2);
This give you the array structure you are looking for:
<pre><?php
$subject = 'hello world #level:basic #lang:java:php';
$array = explode('#', $subject);
foreach($array as &$value) {
$items = explode(':', trim($value));
if (sizeof($items)>1) $value = $items;
}
print_r($array);
But if you prefer you can use this abomination:
$subject = 'hello world #level:basic #lang:java:php';
$pattern = '~(?:^| ?+#)|(?:\G([^#:]+?)(?=:| #|$)|:)+~';
preg_match_all($pattern, $subject, $matches);
array_shift($matches[1]);
$lastKey = sizeof($matches[1])-1;
foreach ($matches[1] as $key=>$match) {
if (!empty($match)) $temp[]=$match;
if (empty($match) || $key==$lastKey) {
$result[] = (sizeof($temp)>1) ? $temp : $temp[0];
unset($temp);
}
}
print_r($result);

Finding tags in query string with regular expression

I have to set some routing rules in my php application, and they should be in the form
/%var/something/else/%another_var
In other words i beed a regex that returns me every URI piece marked by the % character, String marked by % represent var names so they can be almost every string.
another example:
from /%lang/module/controller/action/%var_1
i want the regex to extract lang and var_1
i tried something like
/.*%(.*)[\/$]/
but it doesn't work.....
Seeing as it's routing rules, and you may need all the pieces at some point, you could also split the string the classical way:
$path_exploded = explode("/", $path);
foreach ($path_exploded as $fragment) if ($fragment[0] == "%")
echo "Found $fragment";
$str='/%var/something/else/%another_var';
$s = explode("/",$str);
$whatiwant = preg_grep("/^%/",$s);
print_r($whatiwant);
I don’t see the need to slow down your script with a regex … trim() and explode() do everything you need:
function extract_url_vars($url)
{
if ( FALSE === strpos($url, '%') )
{
return $url;
}
$found = array();
$parts = explode('/%', trim($url, '/') );
foreach ( $parts as $part )
{
$tmp = explode('/', $part);
$found[] = ltrim( array_shift($tmp), '%');
}
return $found;
}
// Test
print_r( extract_url_vars('/%lang/module/controller/action/%var_1') );
// Result:
Array
(
[0] => lang
[1] => var_1
)
You can use:
$str = '/%lang/module/controller/action/%var_1';
if(preg_match('#/%(.*?)/[^%]*%(.*?)$#',$str,$matches)) {
echo "$matches[1] $matches[2]\n"; // prints lang var_1
}

Categories