Is there any way to achieve the following? I need to take this $query and split it into its various elements (the reason is because I am having to reprocess an insert query). As you can see this will work for regular string blocks or numbers, but not where a number, occurs in the string. Is there a way to say |\d but not where that \d occurs within a ' quoted string '?
$query = "('this is\'nt very, funny (I dont think)','is it',12345,'nope','like with 2,4,6')";
$matches = preg_split("#',|\d,#",substr($query,1,-1));
echo $query;
print'<pre>[';print_r($matches);print']</pre>';
So just to be clear about expected results:
0:'this is\'nt very, funny (I dont think)'
1:'it is'
2:12345
3:'nope'
4:'like with 2,4,6'.
** Additionally I don't mind if each string is not quoted - I can requote them myself.
Could (*SKIP)(*F) parts that are inside single quotes and match ,
outside:
'(?:\\'|[^'])*'(*SKIP)(*F)|,
(?:\\'|[^'])
Inside the single quotes matches escaped \'
or a character that is not a single quote.
$query = "('this is\'nt very, funny (I dont think)','is it',12345,'nope','like with 2,4,6')";
$matches = preg_split("~'(?:\\\\'|[^'])*'(*SKIP)(*F)|,~", substr($query,1,-1));
print_r($matches);
outputs to (test at eval.in)
Array
(
[0] => 'this is\'nt very, funny (I dont think)'
[1] => 'is it'
[2] => 12345
[3] => 'nope'
[4] => 'like with 2,4,6'
)
Not absolutely sure, if that is what you mean :)
('(?:(?!(?<!\\)').)*')|(\d+)
Try this.Grab the captures.Each string is quoted as well.See demo.
You could try matching through preg_match_all
instead of splitting.
<?php
$data = "('this is\'nt very, funny (I dont think)','is it',12345,'nope','like with 2,4,6')";
$regex = "~'(?:\\\\'|[^'])+'|(?<=,|\()[^',)]*(?=,|\))~";
preg_match_all($regex, $data, $matches);
print_r($matches[0]);
?>
Output:
Array
(
[0] => 'this is\'nt very, funny (I dont think)'
[1] => 'is it'
[2] => 12345
[3] => 'nope'
[4] => 'like with 2,4,6'
)
If you don't mind using preg_match
, then the solution could look like this. This regex uses lookbehind with negative assertions (?<!\\\\)
, it will match strings inside quotes that is not preceded by slash, and the alternation with the vertical bar ensures that numbers that are part of larger match will be ignored.
$query = "('this is\'nt very, funny (I dont think)','is it',12345,'nope','like with 2,4,6',6789)";
preg_match_all( "/(?<!\\\\)\'.+?(?<!\\\\)\'|\d+/", substr( $query, 1, -1 ), $matches );
print_r( $matches );
/* output:
Array (
[0] => Array
(
[0] => 'this is\'nt very, funny (I dont think)'
[1] => 'is it'
[2] => 12345
[3] => 'nope'
[4] => 'like with 2,4,6'
[5] => 6789
)
)
*/
,(?=(?:[^']*'[^']*')*[^']*$)
Try this.This will split according to what you want.Replace by .See demo.