Skip to main content

Regex

Regular expressions (regex) are powerful tools for pattern matching and text manipulation. Here's how different languages handle regex operations.

Basic Pattern Matching​

// Create regex
const pattern = /hello/i; // literal with flag
const pattern2 = new RegExp("hello", "i"); // constructor

// Test match
pattern.test("Hello World"); // true

// Find match
"Hello World".match(/hello/i); // ["Hello"]
"Hello World".search(/hello/i); // 0 (index)

// Find all matches
"hello hello".match(/hello/g); // ["hello", "hello"]

Replace Operations​

// Replace first match
"Hello World".replace(/hello/i, "Hi"); // "Hi World"

// Replace all matches
"hello hello".replace(/hello/g, "Hi"); // "Hi Hi"

// Replace with function
"hello world".replace(/\w+/g, (match) => match.toUpperCase()); // "HELLO WORLD"

Capture Groups​

// Capture groups
const match = "John Doe".match(/(\w+) (\w+)/);
// match[0] = "John Doe"
// match[1] = "John"
// match[2] = "Doe"

// Named groups (ES2018+)
const named = /(?<first>\w+) (?<last>\w+)/.exec("John Doe");
named.groups.first; // "John"
named.groups.last; // "Doe"

// Use in replace
"John Doe".replace(/(\w+) (\w+)/, "$2, $1"); // "Doe, John"

Common Patterns​

// Email
/^[\w\.-]+@[\w\.-]+\.[a-z]{2,}$/i

// Phone (US)
/^\+?1?[-. ]?\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/

// URL
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/

// Digits only
/^\d+$/

// Alphanumeric
/^[a-zA-Z0-9]+$/

Key Takeaways​

  • Built-in vs library support — JavaScript (/pattern/ or new RegExp), Python (re module), Ruby (/pattern/), Java (Pattern/Matcher), C# (Regex), C++ (<regex>), and Go (regexp) include regex in the standard library. C requires POSIX regex.h or a library like PCRE; Zig has no built-in regex and typically uses external libraries; Rust needs the regex crate. If you're building a project that heavily uses pattern matching, prefer a language with built-in support; for systems or embedded work, factor in library dependencies.

  • Syntax variations — Most languages use PCRE-style patterns. JavaScript and Ruby allow literal syntax: /hello/i for case-insensitive. Go and Rust use string-based patterns: Regex::new(r"(?i)hello") in Rust or regexp.Compile("(?i)hello") in Go. Replace operations also differ: Ruby's "hello hello".gsub(/hello/, "Hi") vs. Python's re.sub(r"hello", "Hi", text). When porting regex between languages, watch for escaping differences—especially in string literals where backslashes may need doubling.

  • Capture groups — Named groups (?<first>\w+) (?<last>\w+) are supported in JavaScript, PHP, Rust, Python, C#, Java, and Ruby, giving clean access like match.groups.first or caps["first"]. C's POSIX regex provides regmatch_t for positional groups but not named groups; Swift's NSRegularExpression exposes ranges by index, requiring manual extraction. For parsing structured text (e.g., log lines, config files), prefer a language with named group support to keep code readable.

  • API ergonomics — Ruby and JavaScript offer the most concise syntax: "Hello World" =~ /hello/i returns the match index; "hello hello".gsub(/hello/, "Hi") does replace-all in one line. C, C++, and Swift require more boilerplate: opening files, iterating with sregex_iterator, converting NSRange to String indices. For quick text processing and scripting, choose Ruby, Python, or JavaScript; for performance-critical or low-level code, accept the verbosity of C/C++ or the explicit APIs of Rust and Go.