Regex (PHP) Удалите все горизонтальные пробелы, кроме кавычек ("" и '') (включая экранированные кавычки) - PullRequest
2 голосов
/ 19 марта 2019

Используя preg_replace (PHP), я хочу удалить все горизонтальные пробелы, кроме пробелов, найденных между кавычками ("" и '') (включая экранированные кавычки)

Пример (регулярное выражение должно повернуть левую сторону в правую сторону):

2 + 2                    => 2+2
f( " ")                  => f(" ")
f("Test \"mystring\" .") => f("Test \"mystring\" .")
f("' ",   " ")           => f("' "," ")

Используя другой пост Я придумал: \h(?=[^']*(?:'[^']*'[^']*)*$)(?=[^"]*(?:"[^"]*"[^"]*)*$)

Который в основном смотрит в будущее и проверяет, есть ли четное количество кавычек до конца строки (как "", так и '').

Однако у меня проблемы с экранированными символами и кавычками внутри кавычек.

" ' test "  => The ' causes problem
" \" test " => The \" causes problem

Я думал об использовании негативных взглядов: (?<!\\)", но не могу заставить его работать. Следующее регулярное выражение терпит неудачу. Не соответствует, когда строка содержит экранированные кавычки.

\h(?=[^"]*(?:(?<!\\)"(?:[^"]*?(?<!\\)")[^"]*?)*$)

1 Ответ

0 голосов
/ 19 марта 2019

Вы можете использовать

'~(?<!\\\\)(?:\\\\{2})*(?:"[^\\\\"]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\')(*SKIP)(*F)|\h+~s'

См. Демоверсию regex

Детали

  • (?<!\\)(?:\\{2})*(?:"[^\\"]*(?:\\.[^"\\]*)*"|'[^\\']*(?:\\.[^'\\]*)*')(*SKIP)(*F) - подстрока '...' или "....", в которой первая кавычка сама по себе не экранирована, которая пропускается после сопоставления (поэтому ничего внутри них не удаляется)
    • (?<!\\) - нет \ символ, разрешенный непосредственно слева от текущего местоположения
    • (?:\\{2})* - ноль или более повторов двойной обратной косой черты
    • (?:"[^\\"]*(?:\\.[^"\\]*)*"|'[^\\']*(?:\\.[^'\\]*)*') - любой из двух вариантов:
      • "[^\\"]*(?:\\.[^"\\]*)*" - строковый литерал внутри двойных кавычек
      • " - двойная кавычка
      • [^\\"]* - 0 или более символов, отличных от \ и "
      • (?:\\.[^"\\]*)*" - ноль или более повторений \, за которыми следует любой символ (\\.), а затем 0 или более символов, отличных от " и \ ([^"\\]*)
      • | - или
      • '[^\\']*(?:\\.[^'\\]*)*' - строковый литерал внутри одинарных кавычек
    • (*SKIP)(*F) - глаголы PCRE, которые пропускают найденное совпадение и заставляют механизм регулярных выражений продолжать поиск следующего совпадения, начиная с текущего индекса регулярного выражения
  • |\h+ - или 1 или более горизонтальных пробелов

Демонстрация PHP :

$strs = ['2 + 2', 'f( " ")', 'f("Test \\"mystring\\" .")', 'f("\' ",   " ")'];
$rx = '~(?<!\\\\)(?:\\\\{2})*(?:"[^\\\\"]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\')(*SKIP)(*F)|\h+~s';
print_r( preg_replace($rx, '', $strs) );

Выход:

Array
(
    [0] => 2+2
    [1] => f(" ")
    [2] => f("Test \"mystring\" .")
    [3] => f("' "," ")
)
...