Regex, чтобы избежать двойных кавычек внутри двойных кавычек с preg_replace

Я пытался избежать всех двойных кавычек внутри двойных кавычек (да, сумасшедший) целый день, и я, наконец, сдаюсь. У меня есть такие данные:

{ "test": "testing with "data" like this", "subject": "trying the "special" chars" } 

Я пытаюсь preg_replace каждый " с \" внутри что-то вроде этого /"(.*)+, "/ что означает все внутри двойных кавычек, за которым следуют запятая и пробел.

Мне нужен способ сделать это:

 { "test": "testing with "data" like this", "subject": "trying the "special" chars" } 

В этом:

 { "test": "testing with \"data\" like this", "subject": "trying the \"special\" chars" } 

Использование preg_replace.

Глядя на ваше регулярное выражение, я предлагаю прочитать жадность regex. Если вы выбираете все между кавычками в первую запятую, вы столкнетесь с проблемами. Первое, что вернулось, было бы test": "testing with "data" like this поэтому, если вы замените все " на \" вы бы test\": \"testing with \"data\" like this что явно не так вы хотите. Я бы рекомендовал использовать что-то вроде этого:

 /"((?:.|\n)*?)"\s*[:,}]\s*/ 

объяснение

  • "((?:.|\n)*?)" – фиксирует любой символ между двумя котировками; минимальная сумма при сохранении шаблона
  • \s* – соответствует 0 или более символам пробела
  • [:,}] – совместить символ двоеточия, запятой или правой скобки
  • \s* – соответствует 0 или более символам пробела

Используя это регулярное выражение и ваши данные, первое, что вернулось, это test . Следующее, что вернулось, будет testing with "data" like this поэтому после замены у вас будет testing with \"data\" like this .


ОБНОВИТЬ

 $test = '{ "test": "testing with "data" like this", "subject": "trying the "special" chars" }'; $pattern = '/"((?:.|\n)*?)"\s*[:,}]\s*/'; preg_match_all($pattern, $test, $matches); foreach($matches[1] as $match){ $answers[] = str_replace('"','\\"',$match); } print_r($answers); // Outputs // Array ( [0] => test [1] => testing with \"data\" like this [2] => subject [3] => trying the \"special\" chars ) 


ОБНОВЛЕНИЕ 2

Я думаю, используя preg_match_all а затем str_replace – лучший способ решить вашу проблему, потому что это регулярное выражение намного более стабильно. Но если вы настаиваете на использовании preg_replace вы можете использовать этот код:

 $string = '{ "test": "testing with "data" like this", "subject": "trying the "special" chars" }'; $pattern = '/(?<!:|: )"(?=[^"]*?"(( [^:])|([,}])))/'; $string = preg_replace($pattern, '\\"', $string); print_r($string); //Outputs //{ "test": "testing with \"data\" like this", "subject": "trying the \"special\" chars" } 

объяснение

  • (?<! – начинает отрицательный lookbehind
  • :|: ) 🙂 – соответствует двоеточие или двоеточие с пробелом и заканчивает lookbehind
  • " – соответствует котировке
  • (?= – начинает позитивный просмотр
  • [^"]*? – сопоставлять что-либо, кроме цитаты, минимальная сумма при все еще правильном шаблоне
  • "(( [^:])|([,}])) – соответствует цитате, за которой следует пробел, и всего, кроме двоеточия ИЛИ, оно соответствует цитате, за которой следует либо запятая, либо правая скобка
  • ) – завершает просмотр

Здесь вы можете узнать больше о regex lookaheads. Я думаю, что это регулярное выражение грязно, хотя технически оно работает. Я собирался продолжать играть с ним, чтобы сделать его лучше, но я устал, поэтому я сейчас ложился спать. Это регулярное выражение позволяет более гибко печатать ваши данные. Обе эти работы и любая их комбинация:

 { "test" : "testing with "data" like this" , "subject" : "trying the "special" chars" } {"test":"testing with "data" like this","subject":"trying the "special" chars"}