====== Regular Expressions ====== Same pattern means different things in different tools. This is the table that resolves it. ===== Regex Flavors by Tool ===== ^ Tool ^ Default ^ Upgrade flag ^ | ''grep'' | BRE | ''-E'' for ERE, ''-P'' for PCRE | | ''sed'' | BRE | ''-E'' (or ''-r'') for ERE | | ''awk'' | ERE-ish | gawk has more | | ''rg'' | Rust regex | no backrefs or lookaround | | ''perl'' | PCRE | | | [[ =~ ]] in bash | ERE | | ===== The Differences That Matter ===== ^ Feature ^ BRE (grep/sed default) ^ ERE (''-E'', awk, bash ''=~'') ^ | ''+'', ''?'' quantifiers | ''\+'', ''\?'' (escaped = special) | bare ''+'' ''?'' | | groups | ''\( \)'' | ''( )'' | | alternation | ''\\|'' | ''|'' | | ''{n,m}'' counts | ''\{n,m\}'' | ''{n,m}'' | | backrefs in pattern | ''\1'' | ''\1'' for ERE search; not in rg | Escaped-vs-bare flips between BRE and ERE: in BRE, ''(a)'' is literal parens and ''\(a\)'' is a group; in ERE it's the opposite. **When unsure, use ''-E''.** ===== Universal building blocks ===== . any char \. literal dot * + ? 0+, 1+, 0-1 ^ $ line start/end [abc] set [^abc] negated set [a-z] range {n,m} counts: {3} {2,} {2,5} x|y alternation (ERE) (x|y) group POSIX classes (work everywhere, even BRE): [[:digit:]] [[:alpha:]] [[:alnum:]] [[:space:]] [[:upper:]] [[:lower:]] [[:punct:]] [[:print:]] [[:blank:]] [[:xdigit:]] GNU extras (work in GNU grep/sed both flavors): ''\b'' word boundary, ''\<''/''\>'' word edges, ''\w'' word char, ''\s'' whitespace, ''\B''. PCRE/Rust extras (''grep -P'', ''rg'', perl): ''\d \D \s \S \w \W'', non-greedy ''*?'', named groups ''(?P..)'', lookahead ''(?=..)'' ''(?!..)''. **Note:** ''rg'''s default engine supports NO lookaround/backrefs: add ''rg -P'' to get PCRE2 when you need them. ===== Practical translations ===== # same task, three tools grep -E '^(Mon|Tue)' f sed -nE '/^(Mon|Tue)/p' f rg '^(Mon|Tue)' f # BRE version of the ERE "(a|b)+" grep 'x\(a\|b\)\+y' # hard to read: use -E instead # IPs: ERE grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' # BRE equivalent (don't do this) grep -o '[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}' ===== Substitution notes ===== * sed backrefs in replacement: ''\1''-''\9'', ''&'' = whole match. * rg capture replace: ''rg 'a(\d+)' -r 'num$1''' uses ''$1''. * Case transforms (GNU sed): ''sed 's/\(.*\)/\U\1/''' uppercases. ===== When Regex Fails ===== * Pattern has ''|''/''(''/''{'' and you did not mean regex: ''grep -F''. * Greedy ''.*'' matched too much: use ''[^x]*'' or PCRE ''.*?''. * Matching across lines: ''grep -z'', ''perl -0777'', or awk paragraph mode. Line-oriented tools will not do it with ''$''/''.'' alone. ===== See Also ===== * [[terminal:scripting:start|Scripting Index]] * [[terminal:tools:start|CLI Tools]] * [[terminal:start|Return to terminal]] * [[start|Return to wiki home]]