Expressions régulières en C# (.NET) : guide détaillé
What is it and why? (a real-life analogy)
Imagine you are a librarian in a huge library with millions of books. A reader comes to you and says: "Find me all books with the word 'adventures' in the title, but only those written after 2000, and with a dragon on the cover." If you had to search for each book manually, it would take weeks. But if you had a magic magnifying glass that instantly scans text and finds everything matching your description — that is a regular expression.
In the programming world, regular expressions (or regex) are a powerful tool for searching, replacing, and validating text. This is not just a word search like in Word or Notepad. It is a language for describing text patterns. You tell the program: "Find me everything that looks like an email," or "Check that the password contains at least one digit and one letter," or "Replace all dates from American format (month/day/year) to European format (day.month.year)."
In C# (.NET), regular expressions are not just a built-in function, but a whole powerful library System.Text.RegularExpressions that allows you to work wonders with text. Without regex, you would have to write dozens of lines of code with loops and checks. With regex, you write one line — and the problem is solved.
Important: Regular expressions are like a foreign language. At first, it seems scary and incomprehensible (a bunch of characters like d, ^, $, *), but after practice, you will start "reading" them like plain text. Don't be afraid — we will break everything down step by step.
Theory: how it works internally
To understand how regular expressions work, you need to look "under the hood" of the regex engine in .NET. When you pass a string with a pattern (for example, "d{3}-d{2}-d{4}" to search for a phone number or SNILS), the following happens:
- Pattern compilation: The engine parses your pattern string and turns it into a finite automaton. This is an abstract machine that can be in different states and switch between them depending on which character it sees in the input text.
- Text traversal: The engine starts reading your text character by character. For each character, it checks whether the current state of the automaton can transition to the next one. If yes, it moves forward. If not, it goes back (this is called backtracking) and tries another path.
- Finding matches: When the automaton reaches a final state (successfully "consumed" the entire pattern), the engine records a match: it remembers the position in the text where it started and ended.
- Optimization: .NET uses a very fast engine. It can "remember" failed paths and not traverse them again. This is called caching.
A key concept is greedy and lazy. By default, quantifiers (characters that indicate the number of repetitions, e.g., * or +) work greedily — they try to capture as much text as possible. If you write .* (dot — any character, asterisk — any number), the engine will try to "eat" the entire text to the end, and then start giving characters back to find a match. If you add a question mark — .*? — the quantifier becomes lazy and will capture the minimum possible.
Remember: The regex engine in .NET is an NFA (Nondeterministic Finite Automaton). It is very powerful, supports lookahead and lookbehind, but can be slow on poorly written patterns (the "catastrophic backtracking" effect — more on this later).
Syntax in C# (.NET): all forms and variants
In .NET, regular expressions live in the namespace System.Text.RegularExpressions. The main class is Regex. Let's break down all the basic syntax elements supported specifically in .NET (version .NET 7+ supports the most modern features).
Basic characters (literals)
Any character that is not special searches for itself. For example, the pattern "cat" will find the word "cat" in the text.
Special characters (metacharacters)
| Character | Meaning | Example |
|---|---|---|
. |
Any character except newline ( ) | c.t finds "cat", "cot", "c3t" |
d |
Any digit (0-9) | dd finds "42", "00" |
D |
Any NON-digit | DD finds "ab", "!@" |
w |
Any "word character": letters, digits, underscore | w+ finds "hello", "test_123" |
W |
Any NON-"word character" | W finds space, dot, comma |
s |
Any whitespace character (space, tab, newline) | s finds a space |
S |
Any NON-whitespace character | S+ finds a word |
^ |
Start of string | ^Hello finds "Hello" only at the beginning |
$ |
End of string | world$ finds "world" only at the end |