Соответствующее содержание цитаты - PullRequest
3 голосов
/ 25 августа 2010

Я пытаюсь удалить кавычки из строки. Пример:

"hello", how 'are "you" today'

возвращает

hello, how are "you" today

Я использую php preg_replace.

На данный момент у меня есть пара решений:

(\'|")(.*)\1

Проблема в том, что он соответствует всем символам (включая кавычки) в середине, поэтому результат ($ 2) равен

hello", how 'are "you today'

Обратные ссылки нельзя использовать в классах символов, поэтому я не могу использовать что-то вроде

(\'|")([^\1\r\n]*)\1

чтобы не совпадать с первой обратной ссылкой в ​​середине.

Второе решение:

(\'[^\']*\'|"[^"]*")

Проблема в том, что сюда включены кавычки в обратной ссылке, поэтому на самом деле ничего не происходит. Результат (1 доллар):

"hello", how 'are "you" today'

Ответы [ 3 ]

3 голосов
/ 25 августа 2010

Вместо:

(\'[^\']*\'|"[^"]*")

Просто напишите:

\'([^\']*)\'|"([^"]*)"
  \______/    \_____/
     1           2

Теперь одна из групп будет соответствовать цитируемому содержимому.

В большинстве случаев, когдагруппа, которой не удалось найти, упоминается в строке замены, в нее подставляется пустая строка, поэтому вы можете просто заменить на $1$2, и одна будет успешным захватом (в зависимости от альтернативы), а другая будет заменена пустойstring.

Вот реализация PHP (, как видно на ideone.com ):

$text = <<<EOT
"hello", how 'are "you" today'
EOT;

print preg_replace(
  '/\'([^\']*)\'|"([^"]*)"/',
  '$1$2',
  $text
);
# hello, how are "you" today 

Более внимательный взгляд

Давайте использовать1 и 2 для кавычек (для наглядности).Также будут добавлены пробелы (для ясности).

Ранее у вас в качестве второго решения был следующий шаблон:

(  1[^1]*1  |  2[^2]*2  )
\_______________________/
   capture whole thing
   content and quotes

Как вы правильно указали, это соответствует паре кавычекправильно (при условии, что вы не можете избежать кавычек), но он не захватывает часть content .

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

1([^1]*)1  |  2([^2]*)2
 \_____/       \_____/
 capture contents from
each alternate separately

Теперь либо группа1 или группа 2 будет захватывать содержимое в зависимости от того, какой альтернативный вариант был найден.В качестве «бонуса» вы можете проверить, какая цитата использовалась, т. Е. Если группа 1 преуспела, то была использована 1.


Приложение

[…] - это класс символов .Нечто вроде [aeiou] соответствует одному из строчных гласных.[^…] - это отрицательный класс символов.[^aeiou] соответствует одному из всего, кроме строчных гласных.

(…) используется для группировки .(pattern) является группой захвата и создает обратную ссылку.(?:pattern) не захватывает.

Список литературы

2 голосов
/ 25 августа 2010

Относительно:

Обратные ссылки не могут использоваться в классах символов, поэтому я не могу использовать что-то вроде

(\'|")([^\1\r\n]*)\1
(\'|")(((?!(\1|\r|\n)).)*)\1

(где (?!...)...) должен работать отрицательно.

Я не знаю, решает ли это вашу основную проблему, но она решает «сопоставить символ, если он не соответствует backref».

Редактировать:

Пропущены скобки, исправлено.

0 голосов
/ 25 августа 2010

Вы не можете сделать это с помощью регулярного выражения. Это требует внутреннего состояния для отслеживания (среди прочего)

  • Обнаружена ли предыдущая кавычка определенного типа
  • Является ли "внешний" уровень котировок текущим уровнем
  • Был ли спущен "внутренний" набор кавычек, и если да, то где этот набор кавычек начинается в строке

Для правильной работы требуется анализатор с грамматикой. Механизм регулярных выражений не сохраняет состояние, потому что это автомат с конечным состоянием, который работает только с текущим входом независимо от предыдущих обстоятельств.

Это та же самая причина, по которой вы не можете надежно сопоставлять наборы вложенных скобок или элементов XML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...