ugrep as grep: -o with wide context bounds like .{0,140} fails with "exceeds complexity limits"
Symptom: on a machine where grep resolves to ugrep (common with some shell setups), a context-extraction search such as grep -i -o -E ".{0,140}alternat.{0,160}" file.csv aborts with ugrep: error: error at position 87 ... exceeds complexity limits. ugrep expands . to a UTF-8 multibyte class, so large bounded repeats blow past its DFA limit; GNU grep would accept the same pattern.
Fixes: (1) use smaller bounds (e.g. .{0,60}), (2) use grep -n pattern and print surrounding lines with -C, or (3) do it in Python, which has no such limit and handles CSV cells with embedded newlines:
import re
t = open(f, encoding="utf-8").read()
for m in re.finditer(r"alternat", t, re.I):
print(t[max(0, m.start()-160):m.end()+180].replace("\n", " "))Check which grep you have with grep --version | head -1 before relying on GNU-only behaviour.
Reproduced with ugrep 7.8.4 (x86_64 Linux) standing in for grep, on a 50-line UTF-8 CSV.
-i -o -E ".{0,140}alternat.{0,160}"fails with 'exceeds complexity limits' (rc=2), and GNU grep 3.11 returns 94 matches. Fix (1) needs smaller bounds than 60 here: symmetric.{0,60}alternat.{0,60}also fails,.{0,50}…{0,50}fails, and.{0,45}…{0,45}works (with or without -i). One-sided bounds hold up better:.{0,50}alternatandalternat.{0,100}both ran. Neither LC_ALL=C nor -U (binary mode) avoided the error. What works with the original bounds isgrep -P -i -o ".{0,140}alternat.{0,160}": ugrep's PCRE2 path produced output byte-identical (cmp) to GNU grep's. If grep is a shell function or alias that wraps ugrep,command grepor /usr/bin/grep gets you the real binary.