php replace group of double backslash - php

how to replace group of double backslash in a string to *
for example:
\\\\a -> **a
\\\a -> *\a
\\a -> *a
\a -> \a
I try use both str_replace and preg_replace but it failed at the second case
str_replace('\\', '*', $str);
preg_replace('/\\\\/', '*', $str);
=> `\\\a` -> `**a`
the reason i want to do this is i want something same as Split string by delimiter, but not if it is escaped but
$str = '1|2\|2|3\\|4\\\|4';
$r = preg_split('~\\\\.(*SKIP)(*FAIL)|\|~s', $str);
var_dump($r);
give me.
0 => string '1' (length=1)
1 => string '2\|2' (length=4)
2 => string '3\|4\\' (length=6)
3 => string '4' (length=1)
i expect something like
[0] => 1
[1] => 2\|2
[2] => 3\\
[3] => 4\\\|4
php 5.4.45-2

A literal backslash in PHP single-quoted strings must be declared with 2 backslashes: to print 1|2\|2|3\\|4\\\|4 you need $str = '1|2\\|2|3\\\\|4\\\\\\|4';.
In a regex, the literal backslash can be matched with 4 backslashes.
Here is an updated PHP code:
$str = '1|2\\|2|3\\\\|4\\\\\\|4';
// echo $str . PHP_EOL; => 1|2\|2|3\\|4\\\|4
$r = preg_split('~\\\\.(*SKIP)(*FAIL)|\\|~s', $str);
var_dump($r);
Result:
array(4) {
[0]=>
string(1) "1"
[1]=>
string(4) "2\|2"
[2]=>
string(3) "3\\"
[3]=>
string(6) "4\\\|4"
}
And to obtain **a from \\a you can thus use
$str = '\\\\a';
$r = preg_replace('~\\\\~s', '*', $str);
See another demo

Related

properly render an array of numeric values, not an array with strings

I have this code in my symfony controller:
$em=$this->getDoctrine()->getManager();
$queryIndex = $em->createQuery( 'SELECT g.index
FROM MySpaceMyBundle:Graphique g');
$result = $queryIndex->getArrayResult();
$arrayResult = array_map('current', $result);
var_dump($arrayResult);
return $this->render('MySpaceMyBundle:MyFolder:myTemplate.html.twig');
With my var_dump, I have this result:
array (size=10)
0 => string '1700.000' (length=8)
1 => string '1200.000' (length=8)
2 => string '1200.000' (length=8)
3 => string '1304.000' (length=8)
4 => string '1800.000' (length=8)
5 => string '2012.000' (length=8)
6 => string '2048.000' (length=8)
7 => string '1048.000' (length=8)
8 => string '3000.000' (length=8)
9 => string '5421.000' (length=8)
But for the obHighchartBundle (using highchart.js) the result I want is:
[1700,1200,1200,1304,1800,2012,2048,1048,3000,5421]
How can I proceed?
Note that I need to pass a numeric array (the values are decimal types in my database), not array with strings.
Like this?
$result = [];
foreach ($arrayResult as $value) {
$result[] = (int) $value
}
var_dump($result);
You can use a tiny tips like array_walk function to cast your values as float to prevent highchart issue. See the documentation for this function:
http://php.net/manual/fr/function.array-walk.php
Here an example of the tiny function :
<?php
function forceFloat (&$aItems) {
$aItems = (float) $aItems;
}
$arrayResult = array("1.00","4.55","39494");
var_dump($arrayResult);
array_walk($arrayResult, 'forceFloat');
var_dump($arrayResult);
?>
The output :
array(3) {
[0]=>
string(4) "1.00"
[1]=>
string(4) "4.55"
[2]=>
string(5) "39494"
}
array(3) {
[0]=>
float(1)
[1]=>
float(4.55)
[2]=>
float(39494)
}
Best Regards,
TGA

PHP - Improve Regex (space and non-capturing group)

I have this kind of string :
$string = "<strong>Blabla1</strong> Blaabla2<br /> Blaabla3 <strong>Blaabla4</strong> Blaabla5 Blaabla6<br /><br /> Blaabla7 <span style='color:#B22222;'>Blaabla8</span> Blaabla9";
I'm trying to explode each word where there is a " " or "<br />" with preg_split .
My conditions :
For each word (Blablax), I need to keep his tags like <strong>, <span>, <em>... but split him after a <br /> or more <br />
I tried this, thanks to another post on stackoverflow :
preg_split('/<br(\s\/)?>\K|\s/',$string,null,PREG_SPLIT_NO_EMPTY);
OUTPUT:
array (size=12)
0 => string '<strong>Blabla1</strong>' (length=24)
1 => string 'Blaabla2<br />' (length=14)
2 => string 'Blaabla3' (length=8)
3 => string '<strong>Blaabla4</strong>' (length=25)
4 => string 'Blaabla5' (length=8)
5 => string 'Blaabla6<br />' (length=14)
6 => string '<br' (length=3)
7 => string '/>' (length=2)
8 => string 'Blaabla7' (length=8)
9 => string '<span' (length=5)
10 => string 'style='color:#B22222;'>Blaabla8</span>' (length=38)
11 => string 'Blaabla9' (length=8)
Everything works except for index 6 and index 7 (see above in OUTPUT) and index 9 and index 10
What I'll exepect :
array (size=12)
0 => string '<strong>Blabla1</strong>' (length=24)
1 => string 'Blaabla2<br />' (length=14)
2 => string 'Blaabla3' (length=8)
3 => string '<strong>Blaabla4</strong>' (length=25)
4 => string 'Blaabla5' (length=8)
5 => string 'Blaabla6<br /><br />' (length=14)
6 => string 'Blaabla7' (length=8)
7 => string '<span style='color:#B22222;'>Blaabla8</span>' (length=45)
8 => string 'Blaabla9' (length=8)
See index 5 and index 7
My regex works if I have just one <br /> but if more than one, there is a mistakes... idem if I have a <span style...>
Thanks !
$string = "<strong>Blabla1</strong> Blaabla2<br /> Blaabla3 <strong>Blaabla4</strong> Blaabla5 Blaabla6<br /><br /> Blaabla7 <span style='color:#B22222;'>Blaabla8</span> Blaabla9";
$matches = preg_split('/(<br.*?>|<span.*>)+\K|\s/sim', $string, null, PREG_SPLIT_NO_EMPTY );
var_dump($matches);
/*
array(9) {
[0]=>
string(24) "<strong>Blabla1</strong>"
[1]=>
string(14) "Blaabla2<br />"
[2]=>
string(8) "Blaabla3"
[3]=>
string(25) "<strong>Blaabla4</strong>"
[4]=>
string(8) "Blaabla5"
[5]=>
string(20) "Blaabla6<br /><br />"
[6]=>
string(8) "Blaabla7"
[7]=>
string(44) "<span style='color:#B22222;'>Blaabla8</span>"
[8]=>
string(8) "Blaabla9"
}
*/
DEMO
Looking at your expected array at index 5 and index 7, you probably want this regex:
preg_split('~(?:</?[a-zA-Z0-9][^>]*+>|\S)++\K|\s~',$string,null,PREG_SPLIT_NO_EMPTY);
Demo on ideone
Output:
array(9) {
[0]=>
string(24) "<strong>Blabla1</strong>"
[1]=>
string(14) "Blaabla2<br />"
[2]=>
string(8) "Blaabla3"
[3]=>
string(25) "<strong>Blaabla4</strong>"
[4]=>
string(8) "Blaabla5"
[5]=>
string(20) "Blaabla6<br /><br />"
[6]=>
string(8) "Blaabla7"
[7]=>
string(44) "<span style='color:#B22222;'>Blaabla8</span>"
[8]=>
string(8) "Blaabla9"
}
The regex attempts to match a full tag, and if a full tag can't be consumed, it will consume one non-space character, then rinse and repeat. This will prevent tags from being split, which gives expected output for index 5 and 7.
I wouldn't recommend doing this with regex, though. I didn't consult the HTML specs when writing the regex, so the regex is very brittle and may break on input in the wild. You might want to learn how to parse HTML properly with one of the libraries listed in this question: How do you parse and process HTML/XML in PHP?
Here is the regex
((?:<br\s*\/?>)+)|(?<!<br)\s+(?!\/?>)
Use this with preg_replace using $1\n as a replacement string, and then you can split by newline to get the array (removing empty ones).
See demo.

Extracting leading spaces from the rest of the string

What is the quickest approach to splitting a string into its leading spaces and the rest of it?
····sth should become array("····", "sth") and ·sth· - array("·", "sth·")
* · = space
$result = preg_split('/^(\s*)/', ' test ', -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
outputs
array(2) {
[0]=>
string(2) " "
[1]=>
string(5) "test "
}
Here's a simpler approach:
$result = preg_split('/\b/', ' sth', 2);
It would output:
array (size=2)
0 => string ' ' (length=3)
1 => string 'sth' (length=3)

PHP - Preg_match_all optional match

I'm having problems matching the[*] which is sometimes there and sometimes not. Anyone have suggestions?
$name = 'hello $this->row[today1][] dfh fgh df $this->row[test1] ,how good $this->row[test2][] is $this->row[today2][*] is monday';
echo $name."\n";
preg_match_all( '/\$this->row[.*?][*]/', $name, $match );
var_dump( $match );
output:
hello $this->row[test] ,how good $this->row[test2] is $this->row[today][*] is monday
array (
0 =>
array (
0 => '$this->row[today1][*]',
1 => '$this->row[test1] ,how good $this->row[test2][*]',
2 => '$this->row[today2][*]',
),
)
Now the [0][1] match takes on too much because it is matching until the next '[]' instead of ending at '$this->row[test]' . I'm guessing the [*]/ adds a wildcard. Somehow need to check if the next character is [ before matching to []. Anyone?
Thanks
[, ] and * are special meta characters in regex and you need to escape them. Also you need to make last [] optional as per your question.
Following these suggestions following should work:
$name = 'hello $this->row[today1][] dfh fgh df $this->row[test1] ,how good $this->row[test2][] is $this->row[today2][*] is monday';
echo $name."\n";
preg_match_all( '/\$this->row\[.*?\](?:\[.*?\])?/', $name, $match );
var_dump( $match );
OUTPUT:
array(1) {
[0]=>
array(4) {
[0]=>
string(20) "$this->row[today1][]"
[1]=>
string(17) "$this->row[test1]"
[2]=>
string(19) "$this->row[test2][]"
[3]=>
string(21) "$this->row[today2][*]"
}
}

Multiple explode characters with comma and - (hyphen)

I want to explode a string for all:
whitespaces (\n \t etc)
comma
hyphen (small dash). Like this >> -
But this does not work:
$keywords = explode("\n\t\r\a,-", "my string");
How to do that?
Explode can't do that. There is a nice function called preg_split for that. Do it like this:
$keywords = preg_split("/[\s,-]+/", "This-sign, is why we can't have nice things");
var_dump($keywords);
This outputs:
array
0 => string 'This' (length=4)
1 => string 'sign' (length=4)
2 => string 'is' (length=2)
3 => string 'why' (length=3)
4 => string 'we' (length=2)
5 => string 'can't' (length=5)
6 => string 'have' (length=4)
7 => string 'nice' (length=4)
8 => string 'things' (length=6)
BTW, do not use split, it is deprecated.
... or if you don't like regexes and you still want to explode stuff, you could replace multiple characters with just one character before your explosion:
$keywords = explode("-", str_replace(array("\n", "\t", "\r", "\a", ",", "-"), "-",
"my string\nIt contains text.\rAnd several\ntypes of new-lines.\tAnd tabs."));
var_dump($keywords);
This blows into:
array(6) {
[0]=>
string(9) "my string"
[1]=>
string(17) "It contains text."
[2]=>
string(11) "And several"
[3]=>
string(12) "types of new"
[4]=>
string(6) "lines."
[5]=>
string(9) "And tabs."
}

Categories