<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged regex</title>
<link>https://coderlegion.com/tag/regex</link>
<description>Powered by Question2Answer</description>
<item>
<title>Why grep &quot;error|failed&quot; finds nothing in a log full of failures</title>
<link>https://coderlegion.com/28026/why-grep-error-failed-finds-nothing-in-a-log-full-of-failures</link>
<description>&lt;p&gt;If grep returns empty on a file you know contains matches, suspect the pattern before the file. Default grep uses Basic Regular Expressions (BRE), where &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, and &lt;code&gt;()&lt;/code&gt; are literal characters unless backslash-escaped. So &lt;code&gt;grep &quot;error|failed&quot; app.log&lt;/code&gt; searches for the literal twelve-character string &lt;code&gt;error|failed&lt;/code&gt; — pipe included — which no logger ever writes. Alternation needs Extended Regular Expressions via &lt;code&gt;-E&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;grep &quot;error|failed&quot; app.log     # BRE: literal string, matches nothing
grep -E &quot;error|failed&quot; app.log  # ERE: matches either word
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The dangerous part is the exit behavior. An impossible pattern is not a syntax error, so grep exits 1 — the same code as &quot;no matches in a clean file&quot; — and prints nothing. A wrong question and a healthy log look identical, which is how this bug hides inside monitoring checks and cron pipelines for days.&lt;/p&gt;
&lt;p&gt;Two related traps: &lt;code&gt;-P&lt;/code&gt; (Perl regex, &lt;code&gt;\d&lt;/code&gt;, lookaheads) is GNU-only and fails on macOS/BSD grep, and bare grep aimed at a directory refuses with &quot;Is a directory&quot; unless &lt;code&gt;-r&lt;/code&gt; is set.&lt;/p&gt;
&lt;p&gt;When I'm unsure what a pattern will match, I assemble the command in this &lt;a rel=&quot;nofollow&quot; href=&quot;https://bashsnippets.xyz/tools/grep-pattern-builder&quot;&gt;grep command builder with a live match tester&lt;/a&gt; — paste a sample line you know should match, and a zero count tells you the pattern is the bug before the empty result gets believed.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/28026/why-grep-error-failed-finds-nothing-in-a-log-full-of-failures</guid>
<pubDate>Thu, 22 Oct 2026 13:00:00 +0000</pubDate>
</item>
<item>
<title>Regular Expression - A Comprehensive Guide</title>
<link>https://coderlegion.com/3193/regular-expression-a-comprehensive-guide</link>
<description>&lt;p&gt;(Originally posted on Methodox Wiki, visit &lt;a rel=&quot;nofollow&quot; href=&quot;https://wiki.methodox.io/en/KnowledgeBase/Regex&quot;&gt;the page&lt;/a&gt; for a live tester!)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Contents&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#h-1-introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#h-2-live-tester&quot;&gt;Live Tester&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#h-3-practical-syntax&quot;&gt;Practical Syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#h-4-comprehensive-reference&quot;&gt;Comprehensive Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#h-5-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(Due to CoderLegion content length limit, section 4 is ommitted)&lt;/p&gt;
&lt;h3 id=&quot;1-introduction&quot;&gt;1. Introduction&lt;/h3&gt;
&lt;p&gt;Text - whether it’s log files, configuration data, user input, or documents - is everywhere in programming. From simple scripts to full-blown applications, developers frequently need to &lt;strong&gt;search&lt;/strong&gt;, &lt;strong&gt;validate&lt;/strong&gt;, &lt;strong&gt;extract&lt;/strong&gt;, or &lt;strong&gt;transform&lt;/strong&gt; pieces of text. While many IDEs and editors (like Notepad++, VS Code, or Sublime Text) offer basic find-and-replace functionality, they quickly reach their limits when you need to handle patterns, conditional logic, or repeated structures. That’s where &lt;strong&gt;regular expressions&lt;/strong&gt; (regex) come in.&lt;/p&gt;
&lt;p&gt;At its core, a regular expression is a compact, declarative way to describe a set of strings. Instead of manually scanning through text to find, say, all warning messages in a log, you can write a single pattern that matches timestamps, log levels, filenames, email addresses, URLs - you name it. Once you understand the fundamentals, regex can become one of the most powerful “weapons” in your developer toolbox.&lt;/p&gt;
&lt;p&gt;Consider a typical log snippet:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2025-05-31 14:23:48 [Info] Starting application...
2025-05-31 14:23:50 [Info] Loading application data...
2025-05-31 14:23:55 [Warning] Missing font file: New Times Roman.
2025-05-31 14:24:22 [Info] The application has started, with 1 warning.
2025-05-31 14:25:01 [Error] Unhandled exception: NullReferenceException.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to answer questions like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“What warnings were emitted, and when?”&lt;/li&gt;
&lt;li&gt;“Which lines contain error messages?”&lt;/li&gt;
&lt;li&gt;“How many times did the application start?”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You could write a script in your favorite language that splits on spaces, checks tokens, and does string comparisons. But that quickly becomes tedious: parsing variability in timestamps, handling optional fields, or ignoring whitespace quirks can make your code fragile.&lt;/p&gt;
&lt;p&gt;With a well-crafted regex, however, you can match on the entire log line, capture the timestamp, the log level, and the rest of the message - all in one pattern. More importantly, regex can handle &lt;strong&gt;any&lt;/strong&gt; text-based format for which there’s a consistent structure: CSV files, HTML/XML tags, custom configuration formats, and so on.&lt;/p&gt;
&lt;p&gt;By the end of this article, you will:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Understand the basic motivation behind regular expressions.&lt;/li&gt;
&lt;li&gt;See practical syntax elements and examples for day-to-day tasks.&lt;/li&gt;
&lt;li&gt;Have a handy reference that summarizes the most commonly used regex constructs.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Whether you’ve done a bit of “find and replace” in an editor, or you’ve written simple string processing code, this guide will bridge the gap and show you how to level up with regular expressions.&lt;/p&gt;
&lt;h3 id=&quot;2-live-tester&quot;&gt;2. Live Tester&lt;/h3&gt;
&lt;p&gt;See &lt;a rel=&quot;nofollow&quot; href=&quot;https://wiki.methodox.io/en/KnowledgeBase/Regex#h-2-live-tester&quot;&gt;original post&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;3-practical-syntax&quot;&gt;3. Practical Syntax&lt;/h3&gt;
&lt;p&gt;In this section, we’ll cover the core building blocks of regex patterns. Each subsection introduces a concept, followed by real-world examples - some based on log processing, others on everyday tasks like validating email addresses or extracting numbers from text.&lt;/p&gt;
&lt;h4 id=&quot;3-1-literal-characters-and-simple-matches&quot;&gt;3.1 Literal Characters and Simple Matches&lt;/h4&gt;
&lt;p&gt;At the simplest level, a regex can be just literal characters. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pattern &lt;code&gt;Error&lt;/code&gt; will match any occurrence of the substring “Error” in a text.&lt;/li&gt;
&lt;li&gt;Pattern &lt;code&gt;2025-05-31&lt;/code&gt; will match that exact date string.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, real-world text rarely lines up perfectly. Log messages, for instance, include varying timestamps and different log levels. To match them in a generic way, you need &lt;strong&gt;metacharacters&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Key Point:&lt;/strong&gt; Most characters in a regex match themselves literally, except for special metacharacters (like &lt;code&gt;.&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;\&lt;/code&gt;, etc.). To match a literal period, bracket, or other metacharacter, you must “escape” it with a backslash (&lt;code&gt;\.&lt;/code&gt; to match a literal dot, &lt;code&gt;\[&lt;/code&gt; to match a literal left bracket, and so on).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;3-2-character-classes-and-ranges&quot;&gt;3.2 Character Classes (&lt;code&gt;[]&lt;/code&gt;) and Ranges&lt;/h4&gt;
&lt;p&gt;A &lt;strong&gt;character class&lt;/strong&gt; is a bracketed set of characters that match exactly one character from the set. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[AEIOU]&lt;/code&gt; matches any single uppercase vowel.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[0-9]&lt;/code&gt; matches any digit from 0 through 9.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[A-Za-z0-9_]&lt;/code&gt; matches a typical word character (letter, digit, or underscore).&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;example-1-matching-a-four-digit-year&quot;&gt;Example 1: Matching a Four-Digit Year&lt;/h5&gt;
&lt;p&gt;Suppose you want to match any year between 1900 and 2099:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;^(19|20)[0-9]{2}$
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; are &lt;strong&gt;anchors&lt;/strong&gt; (we’ll cover them in a moment).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(19|20)&lt;/code&gt; matches either “19” or “20”.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[0-9]{2}&lt;/code&gt; matches exactly two digits.&lt;/li&gt;
&lt;li&gt;Altogether, this matches “1900” through “2099”.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;example-2-extracting-log-levels&quot;&gt;Example 2: Extracting Log Levels&lt;/h5&gt;
&lt;p&gt;Given a log line like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2025-05-31 14:23:55 [Warning] Missing font file: New Times Roman.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can match the log level (&lt;code&gt;Info&lt;/code&gt;, &lt;code&gt;Warning&lt;/code&gt;, &lt;code&gt;Error&lt;/code&gt;, etc.) with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\[(Info|Warning|Error|Debug)\]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;\[` and `\]&lt;/code&gt; match literal square brackets.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(Info|Warning|Error|Debug)&lt;/code&gt; matches one of those four words.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you expect additional levels (e.g., &lt;code&gt;Trace&lt;/code&gt; or &lt;code&gt;Fatal&lt;/code&gt;), you can add them inside the parentheses:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\[(?:Info|Warning|Error|Debug|Trace|Fatal)\]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we’ve used &lt;code&gt;(?: … )&lt;/code&gt; to create a &lt;strong&gt;non-capturing group&lt;/strong&gt; (we’ll talk about groups more in section 5).&lt;/p&gt;
&lt;h4 id=&quot;3-3-quantifiers-repetition-control&quot;&gt;3.3 Quantifiers: Repetition Control&lt;/h4&gt;
&lt;p&gt;Quantifiers specify how many times the preceding element should match. The most common quantifiers are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;*&lt;/code&gt; – Match zero or more times (greedy).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+&lt;/code&gt; – Match one or more times (greedy).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?&lt;/code&gt; – Match zero or one time (makes the preceding token optional).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{n}&lt;/code&gt; – Match exactly &lt;em&gt;n&lt;/em&gt; times.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{n,m}&lt;/code&gt; – Match between &lt;em&gt;n&lt;/em&gt; and &lt;em&gt;m&lt;/em&gt; times (inclusive).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{n,}&lt;/code&gt; – Match &lt;em&gt;n&lt;/em&gt; or more times.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;example-3-matching-timestamps&quot;&gt;Example 3: Matching Timestamps&lt;/h5&gt;
&lt;p&gt;A timestamp like &lt;code&gt;2025-05-31 14:23:48&lt;/code&gt; can be matched with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;\d&lt;/code&gt; is shorthand for &lt;code&gt;[0-9]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\d{4}&lt;/code&gt; matches exactly four digits (the year).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-&lt;/code&gt; matches a literal hyphen.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\d{2}&lt;/code&gt; matches two digits (month and day).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\s+&lt;/code&gt; matches one or more whitespace characters (space, tab).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\d{2}:\d{2}:\d{2}&lt;/code&gt; matches &lt;code&gt;HH:MM:SS&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you’re sure there’s exactly one space between date and time, you could use &lt;code&gt;\s&lt;/code&gt; instead of &lt;code&gt;\s+&lt;/code&gt;.&lt;/p&gt;
&lt;h5 id=&quot;example-4-optional-file-extension&quot;&gt;Example 4: Optional File Extension&lt;/h5&gt;
&lt;p&gt;Suppose you have filenames like &lt;code&gt;report.txt&lt;/code&gt; or &lt;code&gt;report&lt;/code&gt;. To match both, you could use:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;^report(?:\.txt)?$
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; ensure we match the entire string.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;(?:\.txt)?&lt;/code&gt; means “optionally match ‘.txt’”.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;\.&lt;/code&gt; matches a literal dot.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;txt&lt;/code&gt; matches “txt”.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;?&lt;/code&gt; after the group makes it optional.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;3-4-anchors-positioning-matches&quot;&gt;3.4 Anchors: Positioning Matches&lt;/h4&gt;
&lt;p&gt;Anchors specify positions in the text rather than actual characters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;^&lt;/code&gt; – Start of the line/string.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$&lt;/code&gt; – End of the line/string.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\b&lt;/code&gt; – Word boundary (between &lt;code&gt;\w&lt;/code&gt; and &lt;code&gt;\W&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\B&lt;/code&gt; – Non-word boundary.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;example-5-lines-starting-with-error-&quot;&gt;Example 5: Lines Starting with “Error”&lt;/h5&gt;
&lt;p&gt;If you want to catch any line that begins with the word “Error” (as a standalone word), you can write:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;^Error\b.*$
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;^Error&lt;/code&gt; ensures the line starts with “Error”.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\b&lt;/code&gt; asserts a word boundary so that “Errors” or “ErrorCode” are not matched.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.*&lt;/code&gt; matches the rest of the line (any character, zero or more times).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$&lt;/code&gt; anchors the end of line.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;3-5-groups-and-capturing&quot;&gt;3.5 Groups and Capturing&lt;/h4&gt;
&lt;p&gt;Parentheses &lt;code&gt;(&lt;/code&gt; and &lt;code&gt;)&lt;/code&gt; serve two main purposes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Grouping&lt;/strong&gt;: Treat multiple tokens as a single unit (often used with quantifiers or alternation).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Capturing&lt;/strong&gt;: Store the text matched by that group for later retrieval (in code or in a replacement string).&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id=&quot;example-6-capturing-timestamps-and-levels&quot;&gt;Example 6: Capturing Timestamps and Levels&lt;/h5&gt;
&lt;p&gt;Given:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2025-05-31 14:23:55 [Warning] Missing font...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You might write:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;^(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})\s+\[(Info|Warning|Error|Debug)\]\s+(.*)$
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;(\d{4}-\d{2}-\d{2})&lt;/code&gt; captures the date (&lt;code&gt;Group 1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(\d{2}:\d{2}:\d{2})&lt;/code&gt; captures the time (&lt;code&gt;Group 2&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(Info|Warning|Error|Debug)&lt;/code&gt; captures the log level (&lt;code&gt;Group 3&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(.*)&lt;/code&gt; captures the rest of the message (&lt;code&gt;Group 4&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In most languages, after matching, you can extract Group 1, Group 2, etc.:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;e.g., in C#: &lt;code&gt;match.Groups[1].Value&lt;/code&gt; gives the date.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to group without capturing (for alternation or quantifier purposes), use &lt;code&gt;(?: … )&lt;/code&gt;. For instance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(?:Info|Warning|Error|Debug)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;does &lt;strong&gt;not&lt;/strong&gt; create a numbered backreference.&lt;/p&gt;
&lt;h4 id=&quot;3-6-common-metacharacters-and-escape-sequences&quot;&gt;3.6 Common Metacharacters and Escape Sequences&lt;/h4&gt;
&lt;p&gt;Some of the most frequently used shorthand and metacharacters include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.&lt;/code&gt; – Matches any character except newline (in most flavors; some allow a “dotall” mode to match newline).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\d&lt;/code&gt; – Digit (equivalent to &lt;code&gt;[0-9]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\D&lt;/code&gt; – Non-digit (equivalent to &lt;code&gt;[^0-9]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\w&lt;/code&gt; – Word character (letter, digit, underscore; &lt;code&gt;[A-Za-z0-9_]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\W&lt;/code&gt; – Non-word character (anything not in &lt;code&gt;\w&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\s&lt;/code&gt; – Whitespace character (space, tab, newline, etc.).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\S&lt;/code&gt; – Non-whitespace character.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\t&lt;/code&gt;, &lt;code&gt;\n&lt;/code&gt;, &lt;code&gt;\r&lt;/code&gt; – Tab, newline, carriage return.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; When writing regexes in code, you often need to escape backslashes. For instance, in C# you can use verbatim string literals (&lt;code&gt;@&quot;\d{4}-\d{2}-\d{2}&quot;&lt;/code&gt;) to avoid double escapes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;3-7-practical-example-extracting-email-addresses&quot;&gt;3.7 Practical Example: Extracting Email Addresses&lt;/h4&gt;
&lt;p&gt;Say you have a document or a configuration file and need to pull out all email addresses. A simple - but not fully RFC‑compliant - pattern is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;\b&lt;/code&gt; – Ensure we start at a word boundary.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[A-Za-z0-9._%+-]+&lt;/code&gt; – One or more letters, digits, dots, underscores, percent signs, plus, or hyphens (the local part before the &lt;code&gt;@&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@&lt;/code&gt; – Literal “@” symbol.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[A-Za-z0-9.-]+&lt;/code&gt; – One or more letters, digits, dots, or hyphens (domain).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\.&lt;/code&gt; – Literal dot.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[A-Za-z]{2,}&lt;/code&gt; – At least two letters for the TLD (e.g., “com”, “org”, “io”).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\b&lt;/code&gt; – End at a word boundary to prevent partial matches (so we don’t match trailing punctuation).&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;testing-it&quot;&gt;Testing It&lt;/h5&gt;
&lt;p&gt;Given:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Please contact *Emails are not allowed* or *Emails are not allowed* for more info. Alternatively, reach out to admin@localhost if testing locally.
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;*Emails are not allowed*&lt;/code&gt; matches.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*Emails are not allowed*&lt;/code&gt; matches.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;admin@localhost&lt;/code&gt; does &lt;strong&gt;not&lt;/strong&gt; match because &lt;code&gt;localhost&lt;/code&gt; has no “&lt;code&gt;.&lt;/code&gt; + two-or-more-letters” TLD.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;3-8-practical-example-validating-north-american-phone-numbers&quot;&gt;3.8 Practical Example: Validating North American Phone Numbers&lt;/h4&gt;
&lt;p&gt;North American Numbering Plan (NANP) phone numbers often look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;123-456-7890&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(123) 456-7890&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;123.456.7890&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+1 (123) 456-7890&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A practical regex might be:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;^(\+1\s?)?           # Optional country code +1 and a space
(?:\(\d{3}\)|\d{3})  # Either (123) or 123
[ .-]?               # Separator: space, dot, or hyphen (optional)
\d{3}                # Next three digits
[ .-]?               # Separator again (optional)
\d{4}$               # Last four digits
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When compacted (and removing whitespace/comments):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;^(\+1\s?)?(?:\(\d{3}\)|\d{3})[ .-]?\d{3}[ .-]?\d{4}$
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; anchor the pattern to the entire string.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(\+1\s?)?&lt;/code&gt; – Optionally match “+1” followed by an optional space.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(?:\(\d{3}\)|\d{3})&lt;/code&gt; – Either three digits inside parentheses or three digits without.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[ .-]?&lt;/code&gt; – Optionally match a space, a dot, or a hyphen.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\d{3}&lt;/code&gt; – Three digits.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[ .-]?&lt;/code&gt; – Separator again.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\d{4}&lt;/code&gt; – Four digits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This pattern will match most common North American formats. By tweaking the groups and quantifiers, you can adapt it for other regions or stricter/looser rules.&lt;/p&gt;
&lt;h4 id=&quot;3-9-practical-example-parsing-log-files&quot;&gt;3.9 Practical Example: Parsing Log Files&lt;/h4&gt;
&lt;p&gt;Returning to our log example, suppose you want to extract &lt;strong&gt;only&lt;/strong&gt; the warning messages and their timestamps. You might apply a regex like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+\[Warning\]\s+(.*)$
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Group 1&lt;/strong&gt; captures the timestamp (&lt;code&gt;2025-05-31 14:23:55&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Group 2&lt;/strong&gt; captures the message itself (&lt;code&gt;Missing font file: New Times Roman.&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In most programming languages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;C#&lt;/strong&gt; (using &lt;code&gt;System.Text.RegularExpressions&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-csharp&quot;&gt;var pattern = @&quot;^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+\[Warning\]\s+(.*)$&quot;;
var matches = Regex.Matches(logContents, pattern, RegexOptions.Multiline);
foreach (Match m in matches) {
    string timestamp = m.Groups[1].Value;
    string message   = m.Groups[2].Value;
    Console.WriteLine($&quot;[{timestamp}] Warning: {message}&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt; (using the &lt;code&gt;re&lt;/code&gt; module):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import re

pattern = r'^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})\s+\[Warning\]\s+(.*)$'
for line in log_contents.splitlines():
    m = re.match(pattern, line)
    if m:
        timestamp = m.group(1)
        message   = m.group(2)
        print(f&quot;[{timestamp}] Warning: {message}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even if you’ve only ever clicked “Replace” in an editor, these examples should give you a clear sense of how powerful a single regex can be. You define &lt;strong&gt;“match everything up until &lt;code&gt;[&lt;/code&gt;Warning&lt;code&gt;]&lt;/code&gt;, then capture whatever comes next”&lt;/strong&gt;, and you get exactly the data you want.&lt;/p&gt;
&lt;h4 id=&quot;3-10-testing-and-debugging-regex&quot;&gt;3.10 Testing and Debugging Regex&lt;/h4&gt;
&lt;p&gt;When you’re new to regex, it’s easy to overlook small mistakes - missing an escape, misplacing a quantifier, forgetting an anchor. Here are a few tips:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use an Online Tester&lt;/strong&gt;&lt;br&gt;
Websites like &lt;a rel=&quot;nofollow&quot; href=&quot;https://regex101.com&quot;&gt;regex101.com&lt;/a&gt; (PCRE, JavaScript, Python), &lt;a rel=&quot;nofollow&quot; href=&quot;http://regexstorm.net/tester&quot;&gt;RegexStorm&lt;/a&gt; (for .NET), or &lt;a rel=&quot;nofollow&quot; href=&quot;https://regexr.com&quot;&gt;regexr.com&lt;/a&gt; let you type your pattern, paste test text, and see matches/highlights in real time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start Simple, Then Grow&lt;/strong&gt;&lt;br&gt;
If you need a complex pattern, start with a small piece. For instance, test just &lt;code&gt;\d{4}-\d{2}-\d{2}&lt;/code&gt; on the date first, then add time, then add log level, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Comment Your Patterns&lt;/strong&gt; (When Supported)&lt;br&gt;
Some languages/flavors support the “extended” or “free-spacing” mode, where you can add whitespace and &lt;code&gt;# comments&lt;/code&gt; inside your regex:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(?x)            # Enable free-spacing mode
^               # Start of line
(\d{4}-\d{2}-\d{2})   # Group 1: Date
\s+             # One or more spaces
(\d{2}:\d{2}:\d{2})   # Group 2: Time
\s+             # One or more spaces
\[Warning\]     # Literal [Warning]
\s+             # One or more spaces
(.*)            # Group 3: Message text
$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This makes maintenance and future edits easier, especially for complex regexes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Escape Early&lt;/strong&gt;&lt;br&gt;
If you need to match special characters (&lt;code&gt;.&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;[&lt;/code&gt;, &lt;code&gt;]&lt;/code&gt;, &lt;code&gt;(&lt;/code&gt;, &lt;code&gt;)&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;^&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;\&lt;/code&gt;), always escape them with a backslash unless you explicitly want their special behavior.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;4-comprehensive-reference&quot;&gt;4. Comprehensive Reference&lt;/h3&gt;
&lt;p&gt;Omitted due to content length limit. Visit &lt;a rel=&quot;nofollow&quot; href=&quot;https://wiki.methodox.io/en/KnowledgeBase/Regex&quot;&gt;Methodox Wiki&lt;/a&gt; for more.&lt;/p&gt;
&lt;h3 id=&quot;5-conclusion&quot;&gt;5. Conclusion&lt;/h3&gt;
&lt;p&gt;By now you should have a solid grasp of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Why&lt;/strong&gt; regular expressions are invaluable for text processing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How&lt;/strong&gt; to write basic patterns: literals, character classes, quantifiers, anchors.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How&lt;/strong&gt; to use groups, lookarounds, and backreferences for more advanced matching.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Which&lt;/strong&gt; tokens and constructs constitute the “core” of most practical regexes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Where&lt;/strong&gt; to look when you need to refresh your memory (the reference section above, or a site like &lt;a rel=&quot;nofollow&quot; href=&quot;http://regexstorm.net/reference&quot;&gt;regexstorm.net/reference&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With a few dozen minutes of practice - writing regexes against sample text - you’ll rapidly gain confidence. Remember:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Test early and often&lt;/strong&gt; in an online tester or your IDE’s “Find in Files” - seeing the matches in real time is far more enlightening than manually eyeballing code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Readability matters.&lt;/strong&gt; If the pattern becomes unreadable, use the free-spacing mode (&lt;code&gt;(?x)&lt;/code&gt;) and add comments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep it simple&lt;/strong&gt; for common tasks. You rarely need the most arcane syntax; matching log levels, dates, email addresses, or basic CSV fields can usually be done with straightforward character classes and quantifiers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once you’ve mastered the basics, you can explore more advanced topics like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Atomic grouping&lt;/strong&gt; and &lt;strong&gt;possessive quantifiers&lt;/strong&gt; (for performance-critical patterns).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recursive patterns&lt;/strong&gt; (in PCRE or some advanced flavors) to match nested constructs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conditional subpatterns&lt;/strong&gt; (in PCRE or .NET) where you test if a group has matched before deciding the next part of the pattern.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But those are topics for another day. For now, lean on the examples and reference sheet above, and try applying regex to your next text‑processing challenge. In no time, you’ll find yourself thinking in patterns - and you won’t look back.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Congratulations on starting your pattern crafting journey! Keep this guide handy, bookmark your favorite regex tester, and remember that a well‑written regular expression often turns hours of manual parsing into a single line of elegant code.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;references&quot;&gt;References&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://regexstorm.net/&quot;&gt;RegStorm for C#&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Syntax Basics</category>
<guid isPermaLink="true">https://coderlegion.com/3193/regular-expression-a-comprehensive-guide</guid>
<pubDate>Mon, 02 Jun 2025 23:03:31 +0000</pubDate>
</item>
<item>
<title>Regular Expressions in Python</title>
<link>https://coderlegion.com/212/regular-expressions-in-python</link>
<description>&lt;h2 id=&quot;mastering-regular-expressions-in-python&quot;&gt;Mastering Regular Expressions in Python&lt;/h2&gt;
&lt;h2 id=&quot;i-introduction&quot;&gt;I. Introduction&lt;/h2&gt;
&lt;p&gt;We all have been regularly searching for keywords in our favourite articles, and also using the &quot;find and replace&quot; feature in our text editors to correct mistakes. All this is done using &lt;strong&gt;Regular Expressions&lt;/strong&gt;, which is the topic of discussion in this article. Regular Expressions or &lt;strong&gt;RegEx&lt;/strong&gt; is a sequence of characters which specify a certain search pattern of strings. Regular Expressions are an integral part of all text processing tasks in text editors and also for text validation of user inputs. In this article, we shall discuss all about regular expressions and practice using the Python ‘re’ module&lt;/p&gt;
&lt;h2 id=&quot;ii-understanding-regular-expressions&quot;&gt;II. Understanding Regular Expressions&lt;/h2&gt;
&lt;p&gt;Regular Expressions or RegEx can be defined as a sequence of characters which form a pattern that can be searched in strings. The characters in a search pattern could be numbers, alphabets, non-alphanumeric characters. We may even want to search for characters at certain positions like the starting or end of a string or at word boundaries. There may be conditions about the number of times we want those characters in the pattern to be repeated. All such conditions help us define our regular expressions.&lt;/p&gt;
&lt;h3 id=&quot;basic-syntax-and-components-of-regex-patterns-&quot;&gt;Basic syntax and components of regex patterns:&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import re
print(re.search(r&quot;^[cd]o{2}.ing\d&quot;,&quot;cooding2&quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=3729979607255424415&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;RegEx comprise the following components:&lt;br&gt;
&lt;strong&gt;1) Literals&lt;/strong&gt;: The characters which match themselves in the string are known as Literals. Suppose we want to match “coding”, then our pattern could simply be “coding”. Here all the characters are literals, with no special meaning attached to any one of them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2) Metacharacters&lt;/strong&gt;: Some characters have special meanings in a regular expression. They are known as Metacharacters. &lt;br&gt;
Examples: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;.&lt;/code&gt; &quot;period&quot;&lt;/strong&gt; is a special character which represent all characters except new line characters. Pattern &lt;code&gt;.at&lt;/code&gt; matches “cat”, “bat”, “mat” etc.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;*&lt;/code&gt; &quot;asterisk&quot;&lt;/b&gt; represents zero or more occurrences of the character preceding it. Pattern &lt;code&gt;ra*t&lt;/code&gt; matches “rt”, “rat”, “raat”, “raaat”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;+&lt;/code&gt; &quot;plus&quot;&lt;/strong&gt; represents one or more occurrences of the preceding element. Pattern &lt;code&gt;ra+t&lt;/code&gt; matches “rat”, “raat”, “raaat” but not “rt”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;?&lt;/code&gt; &quot;question mark&quot;&lt;/strong&gt; represents zero or one occurrence of the preceding element. Pattern &lt;code&gt;ra?t&lt;/code&gt; matches “rat” and “rt” but not “raat”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;^&lt;/code&gt; &quot;caret&quot;&lt;/strong&gt; represents the start of the string. So, the pattern “^a” will match the a in “air” but not in “fair”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;$&lt;/code&gt; &quot;dollar sign&quot;&lt;/strong&gt; represents the end of the string. So, the pattern &lt;code&gt;d$&lt;/code&gt; will match the d in “sad” but not in “fade”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;\&lt;/code&gt; &quot;backslash&quot;&lt;/strong&gt; Helps us escape a metacharacter. Suppose we want to search for a price of item which is 200$ . But in regular expressions $ is metacharacter. The pattern “200$” will search for a pattern of 200 at the end of string. So, if we want the regular expression to treat $ as a literal, we will escape its metacharacter meaning using a “\” symbol. So, we will make our regular expression as “200\$”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Special sequence&lt;/strong&gt;: The symbol &lt;code&gt;\&lt;/code&gt; in combination with some characters indicate a special sequence&lt;br&gt;
 •&lt;code&gt;\d&lt;/code&gt; matches digits 0-9, &lt;br&gt;
 •&lt;code&gt;\w&lt;/code&gt; matches word characters 0-9, a-z, A-Z, and underscore “_” &lt;br&gt;
 •&lt;code&gt;\s&lt;/code&gt; matches any whitespace character (space, tab, newline).&lt;br&gt;
 •&lt;code&gt;\b&lt;/code&gt; matches a word boundary (position between a word character and a non-word character).&lt;br&gt;
 •&lt;code&gt;\D&lt;/code&gt; matches any character that is not a digit.&lt;br&gt;
 •&lt;code&gt;\W&lt;/code&gt; matches any character that is not a word character. &lt;br&gt;
 •&lt;code&gt;\S&lt;/code&gt; matches any character that is not a whitespace character. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3) Character Classes&lt;/strong&gt;: Suppose we want the character in our search pattern to be any one of a set of characters. Then we may use a character class. For example, we may want our word to be “bat” or “mat” then our regular expression will look like: &lt;code&gt;[bm]at&lt;/code&gt;. Here &lt;code&gt;[]&lt;/code&gt; will represent the character class, which includes the characters b and m and any one of these will match our pattern. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4) Quantifiers&lt;/strong&gt;: Suppose we want to specify that our pattern must contain exactly &quot;n&quot; consecutive occurrences of a sub pattern or character. We may use quantifiers in such cases. The quantity is specified inside&lt;code&gt;{}&lt;/code&gt; curly braces. We want to match 3 occurrences of “a”. Our Pattern would be &lt;code&gt;a{3}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5) Anchors&lt;/strong&gt;: These specify the positioning of the characters in a pattern. We have already discussed these anchors like &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;^ start of string&lt;/li&gt;
&lt;li&gt;$ end of string&lt;/li&gt;
&lt;li&gt;\b word boundary&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;iii-getting-started-with-re-module&quot;&gt;III. Getting Started with re Module&lt;/h2&gt;
&lt;p&gt;Python offers a module by the name of ‘re’, which provides regular expression matching operations. Both Unicode strings (str) as well as 8-bit strings (bytes) can be searched using this module.&lt;/p&gt;
&lt;h3 id=&quot;importing-the-re-module-&quot;&gt;Importing the &lt;code&gt;re&lt;/code&gt; module:&lt;/h3&gt;
&lt;p&gt;Python &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/re.html&quot;&gt;‘re’ module&lt;/a&gt; comes as part of the ‘&lt;strong&gt;The Python Standard Library&lt;/strong&gt;’. It is included as a module under the “&lt;strong&gt;Text processing services&lt;/strong&gt;” of the Python Standard Library. So, we do not need to install it separately using pip command like other packages. Rather we can just import the module and use it. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re 
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;overview-of-key-functions-and-methods-in-the-re-module-&quot;&gt;Overview of key functions and methods in the &lt;code&gt;re&lt;/code&gt; module:&lt;/h3&gt;
&lt;p&gt;The entire documentation of the re module can be viewed at the &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/re.html&quot;&gt;official website&lt;/a&gt;. Here we will discuss the commonly used functions and methods of the re module. &lt;br&gt;
&lt;strong&gt;re.search&lt;/strong&gt; :It search a string for the presence of a pattern. Only the first match will be returned.&lt;br&gt;
&lt;strong&gt;re.findall&lt;/strong&gt; :It will find all occurrences of a pattern in a string and return them as a list.&lt;br&gt;
&lt;strong&gt;re.finditer&lt;/strong&gt;:It will return an iterator yielding a Match object for each match.&lt;br&gt;
&lt;strong&gt;re.compile&lt;/strong&gt; :It will compile a pattern into a Pattern object. Using a Pattern object is much more efficient if the same regular expression has to be used again and again.&lt;br&gt;
&lt;strong&gt;re.match&lt;/strong&gt; : It will match a regular expression pattern to the beginning of a string.&lt;br&gt;
Let see a demonstration of these functions.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re

my_text = &quot;do you code daily, code daily to become an expert. I do code a lot&quot;

print(re.search(r'code', my_text)) # only the first occurence is matched

print(re.findall(r'code', my_text)) # all 3 occurences are matched

m = re.finditer(r'code', my_text) # an iterator object is created 
print(m)
for individual_match in m: # loop over the iterator object to see all matches
    print(individual_match)
    
my_pattern = re.compile(r'do')
my_pattern1 =re.compile(r'you')
print(my_pattern.match(my_text)) # the pattern at the beginning of the string matched
print(my_pattern1.match(my_text))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=1929261708470046200&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Regular Expression Objects:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Pattern object&lt;/strong&gt; : It is a compiled &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.python.org/3/library/re.html#regular-expression-objects&quot;&gt;regular expression object&lt;/a&gt; returned by re.compile(). It offers methods like &lt;code&gt;Pattern.match&lt;/code&gt; and &lt;code&gt;Pattern.search&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Match object&lt;/strong&gt;: It is returned by successful matches and searches.&lt;br&gt;
It offers methods like &lt;code&gt;Match.group&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note&lt;/em&gt;&lt;/strong&gt;: Always use the Python's &lt;strong&gt;raw string notation&lt;/strong&gt; &lt;code&gt;r&quot;your_pattern&quot;&lt;/code&gt; for Regular Expressions to avoid unexpected behaviour. Raw strings allow you to use backslashes &lt;code&gt;\&lt;/code&gt; without needing to escape them. Unlike regular strings, where backslashes have special meanings like \n representing a new line, within a raw string, &lt;code&gt;\&lt;/code&gt; retains its literal value.&lt;/p&gt;
&lt;h2 id=&quot;iv-basic-regex-patterns-and-operations&quot;&gt;IV. Basic Regex Patterns and Operations&lt;/h2&gt;
&lt;p&gt;Let us now practically explore some of the concepts we have learnt till now. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re

my_text = &quot;&quot;&quot;when I start writing, I understand that when
cat and bat are two different words / 1 and 9 
are different digits in maths!&quot;&quot;&quot;

# Matching literal characters
print(re.findall(r'cat',my_text))

# Matching character classes without range
print(re.findall(r'[cb]at',my_text))

# Matching character classes with range
print(re.findall(r'[b-m]at',my_text))

# character class inversions using Caret ^ inside square brackets
print(re.findall(r'[^\w\s]',my_text))

#Quantifiers for matching repetitions
print(re.findall(r'f{2}',my_text))

#Anchors for boundary matching
print(re.findall(r'\b[b-m]at\b',my_text)) # word boundary
print(re.findall(r'^when',my_text)) # string boundary
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=15367879058503299801&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-matching-literal-characters-&quot;&gt;A.Matching literal characters:&lt;/h3&gt;
&lt;p&gt;Here we start by trying to find the simple literal keyword “cat” in a string called “my_text”.&lt;/p&gt;
&lt;h3 id=&quot;b-using-character-classes-and-ranges-&quot;&gt;B. Using character classes and ranges:&lt;/h3&gt;
&lt;p&gt;• Next, we try to match either cat or bat by using character class where we enclose c and b inside the square bracket [cb]. That means if either c or b is present it will be a match.&lt;br&gt;
• Taking this a step further we specify a range of characters, [b-m] any character between this range including b and m will match. &lt;br&gt;
• We could even say that any character except the characters present in the character class by using inversion with a &lt;code&gt;^&lt;/code&gt; Caret sign inside a square bracket&lt;/p&gt;
&lt;h3 id=&quot;c-quantifiers-for-matching-repetitions-&quot;&gt;C. Quantifiers for matching repetitions:&lt;/h3&gt;
&lt;p&gt;We could use quantifiers which specify the exact number of times a character must repeat inside the curly bracket {}. Here we search for “f” repeated twice&lt;/p&gt;
&lt;h3 id=&quot;d-anchors-for-boundary-matching-&quot;&gt;D. Anchors for boundary matching:&lt;/h3&gt;
&lt;p&gt;Here we search for the pattern with word boundary specified with &lt;code&gt;\b&lt;/code&gt; . Note that now “mat” in “maths” and “hat” in “that” do not match as “mat” will not have a word boundary after it and “hat” will not have a word boundary before it.&lt;br&gt;
Similarly, ^ outside of a character class represents a string beginning, so only one “when” at the beginning of the string will be matched. &lt;/p&gt;
&lt;h2 id=&quot;v-advanced-regex-patterns&quot;&gt;V. Advanced Regex Patterns&lt;/h2&gt;
&lt;h3 id=&quot;a-grouping-and-capturing-in-regular-expressions-&quot;&gt;A. Grouping and capturing in regular expressions:&lt;/h3&gt;
&lt;p&gt;When we find patterns using regular expressions, we can create groups of a set of characters by enclosing them in parenthesis (). These groups can then be accessed and processed separately. We may even specify our groups as non-capturing using the notation&lt;code&gt;(?:pattern)&lt;/code&gt;. Also, we can name our groups as well using the notation &lt;code&gt;(?P&amp;lt;name&amp;gt;pattern)&lt;/code&gt; and then access them using those names.  Let’s look at an example:&lt;/p&gt;
&lt;p&gt;Suppose we have a key in our data which looks like “CODE-NAME-DEPT-SALARY-EXPERIENCE”. We can create a regular expression to match this pattern. But if we want to further process the salary and the experience to find the average salary and average experience level of people, then we will create groups for these. We can specify the Name and the age as non-capturing groups here. Let’s look at the example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
salary_list = []
experience_list = []
# CODE-NAME-DEPT-SALARY-EXPERIENCE is the key
my_data = &quot;CODE-Sam-SALES-2300-2 CODE-Tina-TESTING-2600-4 666 CODE-Divya-MARKETING-10000-12 hello&quot;
# pattern1 has 2 non-capturing groups and 2 named groups
pattern1 = r'CODE-(?:\w+)-(?:\w+)-(?P&amp;lt;salary&amp;gt;\d+)-(?P&amp;lt;experience&amp;gt;\d+)'
pattern2 = r'CODE-(\w+)-(\w+)-(\d+)-(\d+)'
m1 = re.finditer(pattern1, my_data)
m2 = re.finditer(pattern2, my_data)
for m in m1:
    print(f&quot;group 1 is for salary: {m.group(1)}&quot;)
    print(f&quot;group 2 is for experience: {m.group(2)}&quot;)
    salary_list.append(int(m.group('salary')))
    experience_list.append(int(m.group('experience')))
print(f&quot;Average salary is : {sum(salary_list)/len(salary_list)}&quot;)
print(f&quot;Average experience level is : {sum(experience_list)/len(experience_list)}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=6522406485857634665&quot; alt=&quot;&quot;&gt;    &lt;/p&gt;
&lt;h3 id=&quot;b-alternation-and-conditional-matching-&quot;&gt;B. Alternation and conditional matching:&lt;/h3&gt;
&lt;p&gt;Regular expressions can also be used to match alternate patterns. Then depending on which pattern has been captured we can further conditionally match other patterns. The &lt;code&gt;|&lt;/code&gt; operator is used for alternation and the &lt;code&gt;(?(id/name)yes|no)&lt;/code&gt; syntax could be used for conditional matching. Let us suppose we want to capture a word say “one” but we have two different languages. If it is English we capture “one”, if it is French we capture “un”. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
my_text = &quot;ENGLISH:one&quot;
my_text1 = &quot;FRENCH:un&quot;
my_text2 = &quot;FRENCH:one&quot;
pattern = r'((ENGLISH)|(FRENCH)):(?(2)(one)|(un))'
m = re.search(pattern, my_text)
m1 = re.search(pattern, my_text1)
m2 = re.search(pattern, my_text2)
print(m)
print(m1)
print(m2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=4061810992727377157&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;c-lookahead-and-lookbehind-assertions-&quot;&gt;C. Lookahead and lookbehind assertions:&lt;/h3&gt;
&lt;p&gt;We can check if our regular expression pattern we are searching for has or does not have an expression before it or after it. Let the pattern to be searched be called X, and the expression to be checked before or after it be called Y. The expression Y would not be included as part of the result. The syntax for this would be:&lt;br&gt;
Positive Lookahead : X(?=Y) &lt;br&gt;
Negative Lookahead: X(?!Y)&lt;br&gt;
Positive Lookbehind : (?&amp;lt;=Y)X&lt;br&gt;
Negative Lookbehind: (?&amp;lt;!Y)X&lt;br&gt;
Let us look at an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
my_text = &quot;onehello1 zerohello2 hello3one hello4zero&quot;
pos_lookahead = r'(hello\d)(?=one)' # r'hello\d' followed by one
neg_lookahead = r'(hello\d)(?!one)' # r'hello\d' not followed by one
pos_lookbehind = r'(?&amp;lt;=one)(hello\d)' # r'hello\d' preceeded by one
neg_lookbehind = r'(?&amp;lt;!one)(hello\d)' # r'hello\d' not preceeded by one 
print(re.findall(pos_lookahead, my_text))
print(re.findall(neg_lookahead, my_text))
print(re.findall(pos_lookbehind, my_text))
print(re.findall(neg_lookbehind, my_text))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=10520393339409454048&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;d-backreferences-&quot;&gt;D.Backreferences:&lt;/h3&gt;
&lt;p&gt;Backreferences in a pattern allow us to specify that the contents found in an earlier capturing group must also be found at the current location in the string. Let us suppose we want to find the words which have the same starting and ending letter. We could then use backreference to capture such words.&lt;br&gt;
Previously captured groups can be referred to by using backslash followed by the group number (e.g., \1, \2, \3, etc.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
my_text = &quot;In this harsh world , when the going gets tough the tough gets going&quot;
pattern = r'\b(\w)\w*\1\b' # will match words which begin and end in the same letter
all_matches =(re.finditer(pattern, my_text))
for match in all_matches:
    print(match)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=2096174085607784991&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;vi-practical-examples-and-use-cases&quot;&gt;VI. Practical Examples and Use Cases&lt;/h2&gt;
&lt;h3 id=&quot;a-validating-input-data&quot;&gt;A. Validating input data&lt;/h3&gt;
&lt;p&gt;Suppose, we wish to validate the user input form. It may contain pin code. We can create a regular expression and use it to validate the particular user input. Suppose we wish to validate the Indian PIN code. Let’s keep the validation rules simple:&lt;br&gt;
PIN code is exactly six-digit long code. &lt;br&gt;
The first digit is 1-9, all other digits can be 0-9. (There are exceptions though, as some of the PIN codes might not exist.)&lt;br&gt;
Regular expression pattern will be “[1-9]\d{5}”&lt;br&gt;
Now we can validate the user input PIN code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re
entered_pincode = input(&quot;please input PINCODE\n&quot;)
pattern = r'^[1-9]\d{5}$'
if re.match(pattern, entered_pincode):
    print(&quot;valid PINCODE&quot;)
else: 
    print(&quot;Invalid PINCODE&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=4915371968410393684&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;b-extracting-information-from-text-e-g-parsing-log-files-&quot;&gt;B. Extracting information from text (e.g., parsing log files)&lt;/h3&gt;
&lt;p&gt;Regular expressions can be used to extract information from text, like from log files. &lt;br&gt;
Suppose my Log file contains information about users who have logged into a system. Let us try to extract the name of the person who logged into the system as well as the date.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re

my_login_info = &quot;INFO:UserA logged into system on date: 04-11-2024&quot;
pattern = r'INFO:(\b.+\b) logged into system on date: (\b\d{2}-\d{2}-\d{4}\b)'
match = re.search(pattern, my_login_info)
print(match)
if match:
    print(f&quot;The following user logged into the system: {match.group(1)}&quot;)
    print(f&quot;Date of Login: {match.group(2)}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=1616653227037238402&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The extracted information can then be used for further interpretation and analysis. &lt;/p&gt;
&lt;h3 id=&quot;c-search-and-replace-operations-in-text-processing-tasks&quot;&gt;C: Search and replace operations in text processing tasks&lt;/h3&gt;
&lt;p&gt;Suppose we used an incorrect word in a paragraph. We could find and replace every occurrence of that word and substitute it with the correct word.&lt;br&gt;
Let’s say we used weak instead of week and our word editor could not spot this mistake, since it cannot understand the context. Let’s correct this mistake with our regular expression.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re

my_paragraph = &quot;Decorators in weak 32.What do you suppose I should be studying in weak 33? Any tweak?&quot;
misspelled_word = r'\bweak\b'
my_paragraph = re.sub(misspelled_word, &quot;week&quot;, my_paragraph)
print(my_paragraph)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=11779661994725779313&quot; alt=&quot;&quot;&gt;&lt;br&gt;
Note that here tweak was not changed as we had used word boundaries in our regular expression pattern&lt;/p&gt;
&lt;h3 id=&quot;d-filtering-and-cleaning-textual-data-using-regular-expressions&quot;&gt;D. Filtering and cleaning textual data using regular expressions&lt;/h3&gt;
&lt;p&gt;We need to filter and clean our data on a regular basis, so that some further processing can be performed on it. &lt;br&gt;
 For example, suppose we want to find the most frequently used words in a book. The first step would be to clean the text of the book, removing all the special characters, replacing the new line characters “\n”, tabs “\t” etc with only a single space. This can be done using the regular expressions.&lt;br&gt;
Let’s see an example for the same.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import re

my_book = &quot;This happens    to be a very **small** book written in &amp;lt;English&amp;gt;, by a renowed author!!!&quot;
my_book = re.sub(r&quot;[^\w\s]&quot;, &quot;&quot;, my_book)
print(my_book)
my_book = re.sub(r&quot;\s+&quot;, &quot; &quot;, my_book)
print(my_book)
my_word_list = my_book.split(&quot; &quot;)
print(my_word_list)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://logiclair.org/?qa=blob&amp;amp;qa_blobid=11157448960013489598&quot; alt=&quot;&quot;&gt;&lt;br&gt;
So, here we have created a list of words in the book after cleaning the text of the book. &lt;/p&gt;
&lt;h2 id=&quot;vii-tips-and-best-practices&quot;&gt;VII. Tips and Best Practices&lt;/h2&gt;
&lt;div class=&quot;div-green&quot;&gt;
&lt;span class=&quot;alert-header&quot;&gt;Tip:&lt;/span&gt;
&lt;span class=&quot;alert-body&quot;&gt;Compile your regex patterns using re.compile if the same pattern is to be used multiple times&lt;br&gt;
Use character classes whenever possible.&lt;br&gt;
Use non-capturing groups if you do not require to further process them.&lt;br&gt;
Do not forget to escape special characters if you want to match them as Literals&lt;br&gt;
Use flags like re.IGNORECASE if you want your search to be case-insensitive&lt;/span&gt;
&lt;/div&gt;
&lt;h2 id=&quot;viii-conclusion&quot;&gt;VIII. Conclusion&lt;/h2&gt;
&lt;p&gt;The knowledge of Regular Expressions is indispensable for text processing, data manipulation, and pattern matching tasks in real world applications. The Python &lt;code&gt;re&lt;/code&gt; module offers many functionalities related to regular expressions usage. I hope this tutorial provides you with enough information to make you curious enough to explore the power of regular expressions in depth. I would encourage you to read the official documentation of the &lt;code&gt;re&lt;/code&gt; module and explore more functions, methods and flags related to regular expressions. Only practice can help you master Regular expressions!&lt;/p&gt;
</description>
<category>Adv Concepts</category>
<guid isPermaLink="true">https://coderlegion.com/212/regular-expressions-in-python</guid>
<pubDate>Sat, 06 Apr 2024 00:24:25 +0000</pubDate>
</item>
</channel>
</rss>