POSIX正则与PCRE对比:邮箱验证正则在POSIX中无效的原因咨询
Great question! Let’s dive into the specific parts of your regex that don’t play nice with POSIX regular expressions—since POSIX flavors (BRE and ERE) have key differences from the PCRE-style regex you’re using.
1. Non-capturing groups (?:...) aren’t supported in POSIX
POSIX regex (both Basic Regular Expressions and Extended Regular Expressions) doesn’t recognize the (?:...) syntax for non-capturing groups:
- In BRE (the default mode for tools like standard
grep), unescaped()are treated as literal characters, not grouping operators. - In ERE (used with
grep -E,awk, etc.),()creates a capturing group, but there’s no shorthand for non-capturing groups.
Your regex uses (?:...) multiple times (for example, (?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?), which gets interpreted as literal text in POSIX modes—completely breaking the pattern’s intended logic.
2. Quantifier syntax varies between POSIX BRE and ERE
If you’re using the default BRE mode, curly brace quantifiers like {0,61} need to be escaped with backslashes (written as \{0,61\}). Unescaped {} are treated as literal characters in BRE, so your quantifiers won’t work as expected.
Additionally, the + quantifier needs escaping in BRE (written as \+), since unescaped + is just a literal character there.
Fixed POSIX-Compatible Versions
For POSIX ERE (closer to your original pattern)
Replace all non-capturing groups with standard capturing groups (even if you don’t need to use the captured value—POSIX ERE has no non-capturing option):
^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$
For POSIX BRE (standard grep without -E)
Escape all grouping parentheses, curly brace quantifiers, and the + quantifier:
^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]\+@[a-zA-Z0-9]\([a-zA-Z0-9-]\{0,61\}[a-zA-Z0-9]\)\?\(\.[a-zA-Z0-9]\([a-zA-Z0-9-]\{0,61\}[a-zA-Z0-9]\)\?\)*$
Both versions will correctly match hello@yahoo.com in POSIX-compliant tools.
内容的提问来源于stack exchange,提问作者joros lim

