.NET Regex разбор символа новой строки - PullRequest
0 голосов
/ 25 декабря 2009

Я столкнулся с некоторой проблемой. В моей строке может быть специальный символ / символ новой строки '\ r \ n'

Часть моего регулярного выражения:

string sRegex = "(?<string>\"+.*\"|'+.*')";

Как мне изменить это регулярное выражение, чтобы исключить новую строку из моей строки?

Спасибо за помощь.

Ответы [ 4 ]

2 голосов
/ 26 декабря 2009

Вы хотите сказать, что хотите сопоставлять строки в кавычках, только если они не содержат символы новой строки? Если это так, вам не нужно делать ничего особенного, потому что точка не соответствует переводу строки по умолчанию. Помимо + после вступительных кавычек (что для меня не имеет смысла), ваше регулярное выражение должно работать нормально. Но я поддерживаю предложение Джея, чтобы вы использовали дословные строковые литералы для написания регулярных выражений:

Regex sRegex = new Regex(@"(?<string>"".*""|'.*')");

То, что вам нужно нужно остерегаться, - это жадность. Например, если в одной строке два объявления строк, например:

var s1 = "foo", s2 = "bar";

... регулярное выражение найдет одно совпадение, "foo", s2 = "bar", где вы ожидали, что оно совпадет с "foo" и "bar" по отдельности. Чтобы избежать этого, вы можете использовать не жадный квантификатор:

Regex sRegex = new Regex(@"(?<string>"".*?""|'.*?')");

Если вы делаете хотите сопоставить строки с новыми строками в них, вы можете использовать опцию Singleline, которая изменяет поведение точки, позволяя ей сопоставлять строки.

Regex sRegex = new Regex(@"(?<string>"".*?""|'.*?')",
                         RegexOptions.Singleline);

... или вы можете использовать встроенный модификатор:

Regex sRegex = new Regex(@"(?s)(?<string>"".*?""|'.*?')");

Имейте в виду, что когда вы используете точку в однострочном режиме, особенно важно использовать негладкий квантификатор, поскольку потенциальные совпадения больше не ограничиваются одной линией. Но вот еще одна альтернатива, более эффективная и предсказуемая:

Regex sRegex = new Regex(@"(?<string>""[^""]*""|'[^']*')");

Нет необходимости указывать однострочный режим с этим регулярным выражением, потому что вы не используете метасимвол точки. Класс отрицанных символов [^"] соответствует любому символу, кроме кавычки, включая символы новой строки.


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

Все режимы многострочного ввода - это изменение поведения начального и конечного якорей ^ и $. Обычно они соответствуют только началу и концу всей строки, но если вы включите многострочный режим, они также соответствуют началу и концу логических строк в строке. Например, заданная строка объявлена ​​так:

"fee fie\nfoe fum"

Если вы ищете регулярное выражение ^\w+ в режиме по умолчанию, вы получите одно совпадение: fee. Но если вы переключитесь в многострочный режим, вы получите два: fee и foe. Аналогично, \w+$ соответствует только fum в режиме по умолчанию, но соответствует fie и fum в многострочном режиме. И вы всегда можете сопоставить литерал \n независимо от того, в каком режиме вы находитесь: однострочный, многострочный или по умолчанию.

Люди также склонны считать, что однострочные и многострочные являются взаимоисключающими, а это не так. Я даже видел, как люди говорят, что однострочный режим является режимом по умолчанию; тоже не правда. Singleline меняет поведение точки (.), Multiline меняет поведение якорей (^ и $); это все.

2 голосов
/ 25 декабря 2009

Не думаю, что достаточно информации, чтобы полностью ответить на ваш вопрос, но я думаю, что мы можем предоставить вам достаточно информации, чтобы решить ее самостоятельно.

Посмотрите на Regex Workbench (http://code.msdn.microsoft.com/RegexWorkbench). Это отличный инструмент для определения правильного регулярного выражения. Предоставленные двоичные файлы предназначены для очень старого .NET, но вы можете перекомпилировать его. 1007 *

Просмотрите перечисление RegexOptions (http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regexoptions(VS.71).aspx), особенно RegexOptions.MultiLine. Это, вероятно, то, что вам нужно.

Существует два способа задания опций: RegexOptions и «встроенные конструкты» (http://msdn.microsoft.com/en-us/library/yd1hzczs(VS.71).aspx). Например, MultiLine можно указать как:

string sRegex = "(?<string>\"+.*\"|'+.*')?m";

Несколько дополнительных примечаний:

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

Я бы предпочел хранить свое регулярное выражение в объекте Regex, а не в строке, так как это более богатая типизация. Исключение для меня - когда я сочиняю строки для создания нового регулярного выражения. В этом случае я вызываю переменную fooRegexText, чтобы прояснить ситуацию.

Мне трудно читать регулярные выражения любой сложности. Я использую пробел в регулярном выражении, чтобы помочь моему бедному мозгу (используя IgnorePatternWhitespace).

Применяя их, я бы написал:

        Regex regex = new Regex(
@"(?mx) # MultiLine, IgnorePatternWhitespace
    (?<string>
        ""+.*""
            |
        '+.*'
    )
");
2 голосов
/ 25 декабря 2009

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

В dotnet вы хотите сделать:

Regex.Match("string", "regex", RegexOptions.Multiline) 

и "regex" должны содержать строки с явно указанными символами новой строки, например

"regex\nnewline"

, что соответствует внутренним 2 строкам:

hello
regex
newline
world
0 голосов
/ 25 декабря 2009

Вы можете попробовать что-то вроде этого:

string sRegex = "(?<string>\"+(.*[\r\n]*)\"|'+(.*[\r\n]*)*')";

Это должно охватывать строку, подобную этой

"Akim
Khalilov
StackOverflow"

Я уверен, что это регулярное выражение можно оптимизировать.

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

...