Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP preg_replace all commas except those inside parentheses

I'm trying to format a sql statement to make it easier to read.

$sql = "SELECT title, url, author, FROM_UNIXTIME(published, '%Y') AS year FROM articles WHERE id IN(2010,2011,2012)";

expected result:

SELECT
    title,
    url,
    author,
    FROM_UNIXTIME(published, '%Y') AS year 
FROM 
    articles 
WHERE
    id IN(2010, 2011, 2012)

It simply makes those keywords like SELECT, FROM, WHERE... on their own lines,
and then insert a newline + tab after each comma, but, NOT those commas inside parentheses.

here is my attemp

$sql = preg_replace('/(SELECT|FROM[^_]|WHERE)/', "\n$1\n\t", $sql);

function replace_commas($matches) {
    return str_replace(",", ",\n\t", $matches[0]);
}

$sql = preg_replace_callback("/(.*)/s", 'replace_commas', $sql);
//                            ^^^^^^^
//                           stuck here

stuck here: how to exclude those commas inside parentheses in the pattern?

like image 203
user1643156 Avatar asked Nov 05 '12 23:11

user1643156


1 Answers

If you can have an arbitrary number of nested parentheses, you are best off doing it manually within the callback function (by walking the string character-by-character and counting parentheses). If you can assure that you only have one layer of parentheses and all parentheses are matched (so that you have a valid syntax), you could use a lookahead, that asserts that there is no ) until the next ( or the end of the string:

'/,(?=[^)]*(?:[(]|$))/'

You do not even need the callback now. Just use preg_replace.

The problem still is that this will also take into account parentheses within strings in your SQL statement, which is why this problem is generally a bit too tough for regular expressions and can only be solved with them if you impose said conditions.

like image 122
Martin Ender Avatar answered Sep 25 '22 02:09

Martin Ender