This article has been localized into Russian by the community.
Модификаторы Regex
В предыдущих статьях мы говорили о регулярных выражениях и как использовать их в C# для сопоставления, замены и так далее. К этому времени, вы должны были понять мощь регулярных выражений и как они могут помочь вам во множестве ситуаций, но они становятся еще мощнее если знать о возможных модификаторах.
Работая над регулярными выражениями вы можете использовать один или несколько модификаторов для контроля поведения механизма сопоставления. Например, процесс сопоставления Regex обычно чувствителен к регистру. Это означает что "а" не то же самое что "А". Однако, во многих случаях, вы захотите соответствие быть не чувствительным к регистру, т.е. символ "а" будет просто буквой, не важно строчная она или ПРОПИСНАЯ. Просто предоставьте RegexOptions.IgnoreCase параметр при создании экземпляра Regex и соответствия перестанут быть чувствительны к регистру.
Вы найдете все доступные модификаторы в перечислителях RegexOprions. Несколько из них являются общими среди всех языков программирования поддерживающих стандарт регулярных выражений, в то время как другие доступны только для .NET платформы.
В первом примере вы увидите, что Regex модификаторы обычно указываются как второй параметр при создании экземпляра Regex. Вы можете указать больше чем один параметр разделяя их вертикальной чертой (|), вот так:
new Regex("[a-z]+", RegexOptions.IgnoreCase | RegexOptions.Singleline);
Теперь давайте пробежимся по всем модификаторам. Это даст вам представление о том как они работают и как они могут вам помочь.
RegexOptions.IgnoreCase
Этот модификатор скорее всего будет одним из самых вами используемых. Как описано выше, он изменит чувствительность ваших регулярных выражений к регистру на нечувствительный. Это сильно повлияет на результат, как вы можете видеть в этом примере:
public void IgnoreCaseModifier()
{
string testString = "Hello World";
string regexString = @"^[a-z\s]+$";
Regex caseSensitiveRegex = new Regex(regexString);
Regex caseInsensitiveRegex = new Regex(regexString, RegexOptions.IgnoreCase);
Console.WriteLine("Case-sensitive match: " + caseSensitiveRegex.IsMatch(testString));
Console.WriteLine("Case-insensitive match: " + caseInsensitiveRegex.IsMatch(testString));
}
Мы создаем простое регулярное выражение, предназначенное для поиска только букв (a-z) и пробелов. Мы используем его для создания экземпляров Regex: один без RegexOptions.IgnoreCase модификатора и один с ним, и затем и пробуем найти совпадения для одной и той же строки, содержащей буквы в нижнем и ВЕРХНЕМ регистре и один пробел. Вывод будет, что неудивительно, выглядеть следующим образом:
Case-sensitive match: False
Case-insensitive match: True
RegexOptions.Singleline
В регулярных выражениях, точка (.) интерпретируется как "подходит все". Однако, по умолчанию, ей не подходят символы разрыва строки. Это означает что вы можете использовать точку для совпадения всей сроки состоящей из букв, цифр, специальных символов и всех других, но совпадения окончатся при встрече в концом строки. Тем не менее, если вы предоставите модификатор Singleline, разрыв строки будет подходить для точки. Позвольте мне показать различие:
public void SinglelineModifier()
{
string testString =
@"Hello World
This string contains
several lines";
string regexString = ".*";
Regex normalRegex = new Regex(regexString);
Regex singlelineRegex = new Regex(regexString, RegexOptions.Singleline);
Console.WriteLine("Normal regex: " + normalRegex.Match(testString).Value);
Console.WriteLine("Singleline regex: " + singlelineRegex.Match(testString).Value);
}
Вывод будет выглядеть так:
Normal regex: Hello World
Singleline regex: Hello World
This string contains
several lines
RegexOptions.Multiline
Как мы говорили в этой главе, регулярные выражения состоят из множества различных символов для различных целей. Следующим примером будут эти два символа: ^ и $. На самом деле мы уже использовали их в примере с чувствительностью к регистру выше, для сопоставления начала и конца строки. Однако, предоставляя модификатор Multiline, вы можете изменить поведение с совпадения начала/конца строки на совпадения начала/конца строк. Это очень полезно когда вы пытаетесь найти совпадения во множестве строк. Вот пример:
public void MultilineModifier()
{
string testString =
@"Hello World
This string contains
several lines";
string regexString = "^.*$";
Regex singlelineRegex = new Regex(regexString, RegexOptions.Singleline);
Regex multilineRegex = new Regex(regexString, RegexOptions.Multiline);
Console.WriteLine("Singleline regex: " + singlelineRegex.Match(testString).Value);
Console.WriteLine("Multiline regex:");
MatchCollection matches = multilineRegex.Matches(testString);
for(int i = 0; i < matches.Count; i++)
Console.WriteLine("Line " + i + ": " + matches[i].Value.Trim());
}
Заметьте как я использовал тестовый текст (string) состоящий из нескольких строк и затем по разному использовал механизмы поиска совпадений: с singlelineRegex, мы работаем со всем текстом как с одной строкой, даже несмотря на содержание в ней разрывов строк, как мы обсудили выше. Используя multilineRegex мы работаем с тестовым текстом как с несколькими строками, получая результат совпадений для каждой из них. Мы можем использовать Regex.Matches() метод для получения и работы с каждой из строк - в данном случае, мы просто выводим их в консоль.
RegexOptions.Compiled
Несмотря на быструю скорость работы регулярных выражений, если они сложны и исполняются множество раз (в цикле), они могут замедлить работу приложения. В таких ситуациях, вы можете использовать модификатор RegexOptions.Compiled, что позволит платформе компилировать регулярное выражение для сборки. Это будет стоить немного дополнительного времени при создании, если сравнивать с обычным созданием Regex, но это ускорит все последующие Regex операции (поиск совпадений и т.д.):
Regex compiledRegex = new Regex("[a-z]*", RegexOptions.Compiled);
Больше модификаторов
Выше были рассмотрены самые интересные модификаторы, но существуют еще несколько, по которым мы пройдемся немного быстрее:
- RegexOptions.CultureInvariant: с этим модификатором, культурные различия в языке будут проигнорированы. Это в основном уместно если ваше приложение работает с несколькими неанглийскими языками.
- RegexOptions.ECMAScript: изменяет вид Regex с версии .NET на версию стандарта ECMAScript. Пригождается достаточно редко.
- RegexOptions.ExplicitCapture: обычно, пара круглых скобок в Regex ведет себя как разделитель для групп, позволяя обращаться к каждой из них через индекс. Если вы добавите модификатор ExplicitCapture, будет возможно создавать только именованные группы.
- RegexOptions.IgnorePatternWhitespace: если этот модификатор активен, пробелы в Regex игнорируются и у вас также появится возможность добавлять комментарии, начинающиеся с символа решетки (#).
- RegexOptions.RightToLeft: изменяет направление поиска совпадений на справа налево, вместо направления по умолчанию (слева направо).
Резюме
Как вы могли заметить, существует множество Regex модификаторов о которых вы должны знать, чтобы понимать какие варианты использования регулярных выражений существуют.