Use of PHP explode() function - php

I have a problem, I want to split a string variable using the explode function but there are a limitation, imagine having the next string variable with the next value :
$data = "3, 18, 'My name is john, i like to play piano'";
Using the explode function : explode(",", $data), the output will be :
array(
[0] => 3,
[1] => 18,
[2] => 'My name is john,
[3] => i like to play piano'
);
My target is to split the variable $data by comma excluding the ones that are between ' ' chatacters.
e.g. array(
[0] => 3,
[1] => 18,
[2] => 'My name is john, i like to play piano'
);
If anyone can tell me a way to do this, I'd be grateful.

This looks rather like CSV data. You can use str_getcsv to parse this.
var_dump(str_getcsv("3, 18, 'My name is john, i like to play piano'", ',', "'"));
should result in:
array(3) {
[0] =>
string(1) "3"
[1] =>
string(3) " 18"
[2] =>
string(12) "My name is john, i like to play piano"
}
You may want to apply trim to each of the array elements too, by using array_map:
$string = "3, 18, 'My name is john, i like to play piano'";
var_dump(array_map('trim', str_getcsv($string, ',', "'")));

Use: str_getcsv
// set the delimiter with ',', and set enclosure with single quote
$arr = str_getcsv ($data, ',', "'");

You can use the str_getcsv() function as:
$data = "3, 18, 'My name is john, i like to play piano'";
$pieces = str_getcsv($data, ',', "'");
The first argument to the function is the string to be split.
The second argument is the delimiter on which you need to split.
And the third argument is the single character that when used as a pair (unsescaped) inside the first argument, will be treated as one field, effectively ignoring the delimiters between this pair.

Related

Get matches from a preg_replace and use them as an array key

I want to get matches from a String and use them in a array as key to change the value in the string to the value of the array.
If it would be easier to realize, i can change the fantasy tags from %! also to whatever don't have problems in JS/jQuery. This script is for external JS Files and change some variables, which I can't Access from JS/jQuery. So I want to insert them with PHP and send them minified and compressed to the Browser.
$array = array ( 'abc' => 'Test', 'def' => 'Variable', 'ghi' => 'Change' );
$string ='This is just a %!abc!% String and i wanna %!ghi!% the %!def!%';
$string = preg_replace('%!(.*?)!%',$array[$1],$string);
echo $string;
You can use array_map with preg_quote to turn the keys of your array into regexes, and then use the values of the array as replacement strings in the array form of preg_replace:
$array = array ( 'abc' => 'Test', 'def' => 'Variable', 'ghi' => 'Change' );
$string ='This is just a %!abc!% String and i wanna %!ghi!% the %!def!%';
$regexes = array_map(function ($k) { return "/" . preg_quote("%!$k!%") . "/"; }, array_keys($array));
$string = preg_replace($regexes, $array, $string);
echo $string;
Output:
This is just a Test String and i wanna Change the Variable
Demo on 3v4l.org

PHP - preg_replace on an array not working as expected

I have a PHP array that looks like this..
Array
(
[0] => post: 746
[1] => post: 2
[2] => post: 84
)
I am trying to remove the post: from each item in the array and return one that looks like this...
Array
(
[0] => 746
[1] => 2
[2] => 84
)
I have attempted to use preg_replace like this...
$array = preg_replace('/^post: *([0-9]+)/', $array );
print_r($array);
But this is not working for me, how should I be doing this?
You've missed the second argument of preg_replace function, which is with what should replace the match, also your regex has small problem, here is the fixed version:
preg_replace('/^post:\s*([0-9]+)$/', '$1', $array );
Demo: https://3v4l.org/64fO6
You don't have a pattern for the replacement, or a empty string place holder.
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject)
Is what you are trying to do (there are other args, but they are optional).
$array = preg_replace('/post: /', '', $array );
Should do it.
<?php
$array=array("post: 746",
"post: 2",
"post: 84");
$array = preg_replace('/^post: /', '', $array );
print_r($array);
?>
Array
(
[0] => 746
[1] => 2
[2] => 84
)
You could do this without using a regex using array_map and substr to check the prefix and return the string without the prefix:
$items = [
"post: 674",
"post: 2",
"post: 84",
];
$result = array_map(function($x){
$prefix = "post: ";
if (substr($x, 0, strlen($prefix)) == $prefix) {
return substr($x, strlen($prefix));
}
return $x;
}, $items);
print_r($result);
Result:
Array
(
[0] => 674
[1] => 2
[2] => 84
)
There are many ways to do this that don't involve regular expressions, which are really not needed for breaking up a simple string like this.
For example:
<?php
$input = Array( 'post: 746', 'post: 2', 'post: 84');
$output = array_map(function ($n) {
$o = explode(': ', $n);
return (int)$o[1];
}, $input);
var_dump($output);
And here's another one that is probably even faster:
<?php
$input = Array( 'post: 746', 'post: 2', 'post: 84');
$output = array_map(function ($n) {
return (int)substr($n, strpos($n, ':')+1);
}, $input);
var_dump($output);
If you don't need integers in the output just remove the cast to int.
Or just use str_replace, which in many cases like this is a drop in replacement for preg_replace.
<?php
$input = Array( 'post: 746', 'post: 2', 'post: 84');
$output = str_replace('post: ', '', $input);
var_dump($output);
You can use array_map() to iterate the array then strip out any non-digital characters via filter_var() with FILTER_SANITIZE_NUMBER_INT or trim() with a "character mask" containing the six undesired characters.
You can also let preg_replace() do the iterating for you. Using preg_replace() offers the most brief syntax, but regular expressions are often slower than non-preg_ techniques and it may be overkill for your seemingly simple task.
Codes: (Demo)
$array = ["post: 746", "post: 2", "post: 84"];
// remove all non-integer characters
var_export(array_map(function($v){return filter_var($v, FILTER_SANITIZE_NUMBER_INT);}, $array));
// only necessary if you have elements with non-"post: " AND non-integer substrings
var_export(preg_replace('~^post: ~', '', $array));
// I shuffled the character mask to prove order doesn't matter
var_export(array_map(function($v){return trim($v, ': opst');}, $array));
Output: (from each technique is the same)
array (
0 => '746',
1 => '2',
2 => '84',
)
p.s. If anyone is going to entertain the idea of using explode() to create an array of each element then store the second element of the array as the new desired string (and I wouldn't go to such trouble) be sure to:
split on or : (colon, space) or even post: (post, colon, space) because splitting on : (colon only) forces you to tidy up the second element's leading space and
use explode()'s 3rd parameter (limit) and set it to 2 because logically, you don't need more than two elements

An effective way to take the appropriate values from the string and add an associative array with the key which coincided from given string

How can I get values from string and put it into an associative array, where the key must be given wildcard string.
Given template is:
param1/prefix-{wildcard1}/{wildcard2}/param2
Given string is:
param1/prefix-name/lastname/param2
The result must be
array('wildcard1' => 'name', 'wildcard2' => 'lastname');
UPD
I want to implement some route script, and wildcards must be variable names that will be injected to script and they will be loaded dynamically from other classes.
I'd first transform template into regex with named capture group, then do the preg_match.
$template = 'param1/prefix-{wildcard1}/{wildcard2}/param2';
// escape special characters
$template = preg_quote($template, '/');
// first, change all {wildcardN} into (?<wildcardN.*?)
$regex = preg_replace('/\\\{([^}]+)\\\}/', "(?<$1>.*?)", $template);
$string = 'param1/prefix-name/lastname/param2';
// do the preg_match using the regex
preg_match("/$regex/", $string, $match);
print_r($match);
Output:
Array
(
[0] => param1/prefix-name/lastname/param2
[wildcard1] => name
[1] => name
[wildcard2] => lastname
[2] => lastname
)

Comma separated list into a non associated array in PHP

I have a string of emails:
$emails = 'email1#example.com, email2#example.com,email3#example.com';
and I need a basic array like [one,two,three] and not [0 => 'one', 1 => 'two', 2 => 'three']. I guess is a non-associative array?
How to do that? I have tried the inbuild 'explode()' PHP function but it creates 0 => one, ... instad of a a simple array email1,email2,..
Besides, explode has problem when there is a space after the comma, so I have to use ', ' or ',' but can't use both.
What PHP function is the best to convert a list of email addresses into a simple non-associative array? Thanks in advance.
First you can remove spaces by str_replace
$emails = str_replace(' ', '', $emails);
and I need a basic array like [one,two,three] and not [0 => 'one', 1 => 'two', 2 => 'three']. I guess is a non-associative arr
In php simple arrays has numeric keys, so it's correct

Group values of array according to regex in PHP

I have an array that looks like this:
[0] => name {
[1] => abc
[2] => def
[3] => }
[4] =>
[5] => othername {
[6] => 123
[7] => 456
[8] => 789
[9] => }
[10] =>
As you can see each group (under each name) can have different amount of lines and different items in them but each group starts with the same regex syntax and ends with a closing } and a blank line after that.
I need to get an array for each group (for each name) recursively. I made a preg_match regex that will find each name line but I don't know how to make an array with that having also all the lines that are before the next name group.
So I want to obtain:
array(
array('name {', 'abc', 'def', '}'),
array('othername {', '123', '456', '789', '}')
)
How can I approach this? Thanks in advance.
Clicquot beat me but I'm not sure his works/is tested. Here's my solution
<?php
$array = array('0' => 'name {', '1' => 'abc', '2' => 'def', '3' => "}\n", '4' => "\n",
'5' => 'othername {',
'6' => '123',
'7' => '456',
'8' => '789',
'9' => '}',
'10' => "\n");
$string = array();
$count = 0;
foreach($array as $value){
$value = trim($value);
$pos = strpos($value, '{');
if ($pos !== false) {
$count++;
}
if(!empty($value)) {
$string[$count][] = $value;
}
}
print_r($string);
Maybe this code is what you asked for. But I'd never use it myself. If you try to build a code parser you shuold look for parsing-trees with a "grammar" or syntax analysis. It is part of parsing and compilers. The slide bellow shows how a compiler or interpreter can work. If you are only aiming to represent your data in order to reach some specific goal, maybe you can look at formats like json. You should always mention in one sentence what your overall goal is prior to asking a specific question.
(sorry for the German)
The issues of the code below are, that syntax variations can break the code, and you are highly voulnerable because the code changes your php variable contents concerning to the contents of your array.
If you are processing a file with code I do recommend you also to process it streight away, instead of first saving it to an array (which costs more memory).
<?php
$syntaxArray = array(
0 => 'name {',
1 => 'abc',
2 => 'def',
3 => '}',
4 => 'othername {',
5 => '123',
6 => '456',
7 => '789',
8 => '}'
);
$regex_open_array = '-(\w+)\s*{-';
$array_open = false;
foreach($syntaxArray as $line){
$matches = array();
if( preg_match($regex_open_array, $line, $matches) ){
if($array_open){
/*recursive array creations do not work - if that's what you need put it in the comments*/
throw new RuntimeException('An array can not be open while the previous array is not closed');
}
$array_open = true;
/*create an array variable
* ....
* isolate the variable name
*/
$currentArray = $matches[1];
/*you can either create a new variable in your php code with the array name or use a big array and use the name as key
* $big_array[$name] = array();
* using this solution every array name must be only used once.
* of course you can use a name twice if you first check prior to creating a new array if the key is already in use.
*/
/*creates a variable with the given name. Must not overwrite an other arrays name like $syntaxArray*/
$$currentArray = array();
}else if($line == '}'){
/*the closing string could be wrapped with trim() or matched with a regex but I followed your example*/
$array_open = false;
}else{
if(!$array_open){
throw new RuntimeException('There is not array currently open');
}
$arr = &$$currentArray;
$arr[] = $line;
}
}
var_dump($name);
var_dump($othername);
Outputs:
array(2) { [0]=> string(3) "abc" [1]=> string(3) "def" } array(3) { [0]=> string(3) "123" [1]=> string(3) "456" [2]=> string(3) "789" }
This isn't really a regex thing. What you want to do is iterate through the array, and check each item. You'd search through the value there for a '{' or a '}'. When you see an opening bracket, you'd set the key in your "condensed" array that you want to index into, and then check subsequent items for a closing bracket. When you see the closing bracket, you'd change the key that you're indexing into in your "condensed" array or whatever and begin anew. When the value isn't a bracket, append it. It'll look something like this (sorry for the bad PHP):
$big_array = array();
$temp_key = NULL;
foreach (array as $key => $value) {
if (strpo($value, '{')) {
$big_array[$key] = array();
$temp_key = $key;
} else if (strpos($value, '}')) {
$temp_key = NULL;
} else {
$big_array[$temp_key].append($value); // or whatever
}
}
This assumes that you having a matching open / close bracket structure , you'd want to add in a ton of error checking of course.

Categories