Одна строка с регулярным выражением и замещающей строкой не будет работать. Первым вашим шагом может быть токенизация входной строки: попробуйте сначала сопоставить комментарии и строковые литералы, а затем попытаться сопоставить символы пробела и, наконец, символы не пробела. Небольшая демонстрация:
$text = <<<BLOCK
SELECT
column1 ,
column2, column3
FROM
table1
-- a comment line ' " ...
WHERE
column1 = 'text, "FROM" \\'from\\\\\\' x' AND
column2 = "sample text 'where' \\"where\\\\\\" " AND
( column3 = 5 )
BLOCK;
echo $text . "\n\n";
preg_match_all('/
--[^\r\n]* # a comment line
| # OR
\'(?:\\\\.|[^\'\\\\])*\' # a single quoted string
| # OR
"(?:\\\\.|[^"\\\\])*" # a double quoted string
| # OR
`[^`]*` # a string surrounded by backticks
| # OR
\s+ # one or more space chars
| # OR
\S+ # one or more non-space chars
/x', $text, $matches);
print_r($matches);
производит:
SELECT
column1 ,
column2, column3
FROM
table1
-- a comment line ' " ...
WHERE
column1 = 'text, "FROM" \'from\\\' x' AND
column2 = "sample text 'where' \"where\\\" " AND
( column3 = 5 )
Array
(
[0] => Array
(
[0] => SELECT
[1] =>
[2] => column1
[3] =>
[4] => ,
[5] =>
[6] => column2,
[7] =>
[8] => column3
[9] =>
[10] => FROM
[11] =>
[12] => table1
[13] =>
[14] => -- a comment line ' " ...
[15] =>
[16] => WHERE
[17] =>
[18] => column1
[19] =>
[20] => =
[21] =>
[22] => 'text, "FROM" \'from\\\' x'
[23] =>
[24] => AND
[25] =>
[26] => column2
[27] =>
[28] => =
[29] =>
[30] => "sample text 'where' \"where\\\" "
[31] =>
[32] => AND
[33] =>
[34] => (
[35] =>
[36] => column3
[37] =>
[38] => =
[39] =>
[40] => 5
[41] =>
[42] => )
)
)
и затем вы можете перебрать свой токенизированный массив $matches
и заменить пробелы в тех местах, где считаете нужным.
Но, как вы, возможно, прочитали в моем уже удаленном комментарии, лучшим вариантом было бы использовать некоторый выделенный синтаксический анализатор SQL для выполнения этого токенизации: я не бегло говорю на SQL, но я вполне уверен, что моя демонстрация выше может быть легко сломана .