Регулярное выражение для C# дословно как строки (обработка ""-подобных escape-выражений)
Я пытаюсь извлечь информацию из rc-файлов. В этих файлах "-чары в строках экранируются путем удвоения их (""), аналогично дословным строкам C#. Есть ли способ извлечь строку?
Например, если у меня есть следующая строка "this is" "test" "", я бы хотел получить это "" test "". Это также должно быть нежадным (очень важно).
Я пытался использовать следующее регулярное выражение;
"(?<text>[^""]*(""(.|""|[^"])*)*)"
Однако выступление было ужасным. Я основал это на объяснении здесь: http://ad.hominem.org/log/2005/05/quoted_strings.php
Кто-нибудь есть идея справиться с этим с помощью регулярного выражения?
5 ответов
У вас есть несколько вложенных квантификаторов повторения. Это может иметь катастрофические последствия для производительности.
Попробуйте что-то вроде этого:
(?<=")(?:[^"]|"")*(?=")
Теперь он может потреблять только две кавычки одновременно... или символы без кавычек. Взгляд назад и взгляд вперед утверждают, что фактическому совпадению предшествует кавычка.
Это также заставляет вас захватывать что-либо. Желаемым результатом будет просто полная строка, которую вы хотите (без внешних кавычек).
Я не утверждаю, что внешние кавычки не удваиваются. Потому что если бы они были, не было бы никакого способа отличить их от пустой строки в любом случае.
Это оказывается намного проще, чем вы ожидаете. Строковый литерал с экранированными кавычками выглядит в точности как набор простых строковых литералов, работающих вместе:
"Some ""escaped"" quotes"
"Some " + "escaped" + " quotes"
Так что это все, что вам нужно, чтобы соответствовать:
(?:"[^"]*")+
Вам придется удалить ведущие и конечные кавычки в отдельном шаге, но это не имеет большого значения. В любом случае вам понадобится отдельный шаг, чтобы убрать экранированные кавычки (\"
или же ""
).
Попробуй это (?<=^")(.*?"{2}.*?"{2})(?="$)
это будет возможно быстрее, чем два предыдущих и без ошибок.
Не, если это лучше или хуже, чем у m.buettner (не догадываясь - он, кажется, знает свое дело), но я подумал, что выкину это для критики.
"(([^"]+(""[^"]+"")*)*)"
- Подходим "начало строки
- Несколько раз соответствуют не "или два"
- Подходим "конец строки"
"([^"]|(""))*?"