Замените пробелы с помощью функции PHP preg_replace, игнорируя строки в кавычках - PullRequest
1 голос
/ 24 мая 2010

Посмотрите на следующую строку :

SELECT
    column1 ,
    column2, column3
FROM
    table1
WHERE
    column1 = 'text, "FROM" \'from\\\' x' AND
    column2 = "sample text 'where' \"where\\\" " AND
    ( column3 = 5 )

Мне нужно экранировать ненужные пробелы из строки, например:

  • удаление пробелов из начало и окончание позиция , () и т. Д.
  • удаление новой строки ( \ r \ n ) и вкладок ( \ t )

Но одна вещь. В процессе удаления не удалось удалить пробелов из строки в кавычках , например:

  • 'текст, "ОТ" \' от \\ 'x'
  • "образец текста" где '\ "где \\" "

и т.д.

мне нужно использовать функцию PHP : preg_replace ($ pattern, $ replace, $ string);

Так что же будет значением $ pattern и $ replace , где значением $ string является данный SQL .

1 Ответ

1 голос
/ 24 мая 2010

Одна строка с регулярным выражением и замещающей строкой не будет работать. Первым вашим шагом может быть токенизация входной строки: попробуйте сначала сопоставить комментарии и строковые литералы, а затем попытаться сопоставить символы пробела и, наконец, символы не пробела. Небольшая демонстрация:

$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, но я вполне уверен, что моя демонстрация выше может быть легко сломана .

...