Разбор .NET Regex символа новой строки

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

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

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

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

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


person Akim Khalilov    schedule 25.12.2009    source источник
comment
венгерское именование на C #, а? ‹Ворчать ворчать›   -  person Jay Bazuzi    schedule 25.12.2009
comment
Было бы полезно, если бы вы могли включить примеры того, что вы хотите сопоставить / исключить.   -  person Jay Bazuzi    schedule 25.12.2009
comment
Возможно, 's' означает строку, которой должно соответствовать регулярное выражение, а не саму строку регулярного выражения. Во всяком случае, можно надеяться. ;)   -  person Alan Moore    schedule 26.12.2009
comment
Вот источник, который мне нужно проанализировать: Cells [89, 6] .Value = \ Some text in russian, 25,, 13. //; 55771; какой-то \ r \ nтекст на русском.; 55771 \   -  person Akim Khalilov    schedule 11.01.2010


Ответы (4)


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

В dotnet вы хотите:

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

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

"regex\nnewline"

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

hello
regex
newline
world
person Marcin    schedule 25.12.2009

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

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

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

Есть два способа указать параметры: RegexOptions и "inline contructs" (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>
        ""+.*""
            |
        '+.*'
    )
");
person Jay Bazuzi    schedule 25.12.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 изменяет поведение якорей (^ и $); это все.

person Alan Moore    schedule 26.12.2009

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

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

Он должен охватывать такую ​​строку

"Akim
Khalilov
StackOverflow"

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

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

person Vadim    schedule 25.12.2009