2012-11-21 3 views
5

Я пытаюсь извлечь информацию из rc-файлов. В этих файлах «символы в строках экранируются путем удвоения их (« ») аналоговых строк строки C#. Это способ извлечь строку?регулярное выражение для C# verbatim like strings (обработка "" -подобных побегов)

Например, если у меня есть следующая строка « это «Ш» тест «»» Я хотел бы получить это„“тест„“. Он также должен быть не жадный (очень важно).

Я пытался использовать следующее регулярное выражение ;.

"(?<text>[^""]*(""(.|""|[^"])*)*)" 

Однако производительность была ужасно I'v на основе его на е xplanation здесь: http://ad.hominem.org/log/2005/05/quoted_strings.php

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

+0

И вы пытаетесь сделать что с помощью Perl? –

+0

Нет. Я использую C#. (Я понимаю Perl и использую его много, но я не могу использовать его для этого приложения) – MartenBE

+0

Тогда почему это имеет тег Perl? : D –

ответ

5

У вас есть некоторые вложенные кванторы повторения. That can be catastrophic for the performance.

Попробуйте что-то вроде этого:

(?<=")(?:[^"]|"")*(?=") 

Это может теперь только потребляем либо две цитаты сразу ... или без кавычек. Lookbehind и lookahead утверждают, что фактическое совпадение предшествует и сопровождается цитатой.

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

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

0

Не делайте это лучше или хуже, чем m.buettner (не угадывая - он, кажется, знает его вещи), но я думал, что выброшу его для критики.

"(([^"]+(""[^"]+"")*)*)" 
+1

Я думаю, что это имеет ту же проблему, что и попытка OP. Но если вы удалите второй '' '' и последний '*', он должен быть почти таким же хорошим, как мой (еще лучше, поскольку он реализует технику оптимизации «Unrolling-the-loop» (@ridgerunner будет петь песню об этом, если он увидит этот ответ: D)). Однако для '+' s требуется по крайней мере один символ без кавычек между двойными кавычками. Вероятно, вы должны сделать эти '*'. (т. е. '' ([^ "] * (" "[^"] *) *) "') –

+0

Большое спасибо за это. Очень признателен. – garyh

0

Попробуйте (?<=^")(.*?"{2}.*?"{2})(?="$) это будет возможно более быстрее, чем два предыдущих и без каких-либо ошибок.

+0

«без каких-либо ошибок», достаточно претензий, вам не кажется? ;) ... это с удовольствием будет соответствовать «что-то» здесь », тогда« »это« »и« так »на« "" ", но не' 'что-то", '" какая-то "" вещь ", ни' «some» «thing» «like» «this» (последний, потому что он не заканчивается тройным кодом, который требуется вашим регулярным выражением) –

2

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

"Some ""escaped"" quotes" 

"Some " + "escaped" + " quotes" 

Так что это все, что вам нужно, чтобы соответствовать его:

(?:"[^"]*")+ 

Вам придется сдирать ведущие и завершающие кавычки на отдельном этапе, но это не имеет большого значения. В любом случае вам понадобится отдельный шаг, чтобы отменить скрытые кавычки (\" или "").

+0

oh, nice catch! +1 –

0
  • Совпадение «начало строки
  • Несколько раз Совпадение не» или два «
  • Соответствует» окончание строки

"([^"]|(""))*?"

Смежные вопросы