regex - split sql statements in php on semicolons (but not inside quotes) -


i have system causing errors when users use semicolon in free format field. have traced down simple explode statement:

$array = explode( ";", $sql ); 

because line in subroutine called on system replace line split things properly, without breaking rest of system. thought onto winner str_getcsv, isn't sophisticated enough either. @ following example

$sql = "begin;insert table_a (a, b, c) values('42', '12', '\'ab\'c; def');insert table_b (d, e, f) values('42', '43', 'xy\'s z ;uvw') on duplicate key update f='xy\'s z ;uvw';commit;";  $array = str_getcsv($sql, ";", "'"); foreach( $array $value ) {     echo $value . "<br><br>"; } 

when run outputs following:

begin

insert table_a (a, b, c) values('42', '12', '\'ab\'c

def')

insert table_b (d, e, f) values('42', '43', 'xy\'s z

uvw') on duplicate key update f='xy\'s z

uvw'

commit

so doesn't notice semicolons inside quotes. (as far can see quoted strings different places in system in single quotes, possible @ times double quotes, not sure that.)

can tell me how this? suspect can complicated regex, on head.

(*skip)(*fail) magic

this live php demo shows output of 2 options below (with or without semi-colon).

this need:

$splits = preg_split('~\([^)]*\)(*skip)(*f)|;~', $sql); 

see demo see splitting on right semi-colons.

output:

[0] => begin [1] => insert table_a (a, b, c) values('42', '12', '\'ab\'c; def') [2] => insert table_b (d, e, f) values('42', '43', 'xy\'s z ;uvw') [3] => commit [4] => 

the empty item #4 match on other side of final ;. other option keep semi-colons (see below).

option 2: keep semi-colons

if want keep semi-colons, go this:

$splits = preg_split('~\([^)]*\)(*skip)(*f)|(?<=;)(?![ ]*$)~', $sql); 

output:

[0] => begin; [1] => insert table_a (a, b, c) values('42', '12', '\'ab\'c; def'); [2] => insert table_b (d, e, f) values('42', '43', 'xy\'s z ;uvw'); [3] => commit; 

explanation

this problem classic case of technique explained in question "regex-match pattern, excluding..."

in left side of alternation |, regex \([^)]*\) matches complete (parentheses) deliberately fails, after engine skips next position in string. right side matches ; word want, , know right ones because not matched expression on left. safe split on it.

in option 2, keep semi-colons, our match on right matches position, no characters. position asserted lookbehind (?<=;), asserts ; precedes position, , negative lookahead (?![ ]*$), asserts follows not optional spaces end of string (so avoid last empty match).

sample code

please examine live php demo.

reference


Comments

Popular posts from this blog

double exclamation marks in haskell -

qml - Is it possible to implement SystemTrayIcon functionality in Qt Quick application -

Qt Creator - Searching files with Locator including folder -