BSD vs GNU grep on macOS CI Runners
macOS runners ship BSD grep, which differs from the GNU grep on Linux runners, most notably by lacking -P.
A grep that works on Ubuntu can fail on a macOS runner because the two greps are different implementations. Knowing the gaps keeps cross-platform pipelines green.
What it does
GNU grep (Linux, most CI images) and BSD grep (macOS) share the common flags but diverge at the edges. BSD grep has no -P (PCRE) and historically lacked some GNU long options. The most reliable cross-platform fixes are to avoid -P, set LC_ALL=C, and install GNU grep on macOS when you need its features.
Common usage
# install GNU grep on a macOS runner (Homebrew)
brew install grep # provides 'ggrep'
ggrep -P '(?<=v)[0-9.]+' file.txt
# portable: avoid -P, use -E instead
grep -Eo 'v[0-9.]+' file.txt
# force byte-wise, locale-stable matching
LC_ALL=C grep '[A-Z]' file.txtOptions
| Difference | GNU vs BSD |
|---|---|
| -P (PCRE) | GNU only; BSD grep has no -P |
| --include / --exclude-dir | GNU; modern BSD grep supports them, older did not |
| --color | Both, but default aliasing differs |
| -z behavior | Both support it; binary handling differs slightly |
| --no-group-separator | GNU only |
In CI
For a single script that runs on both Linux and macOS runners, stick to POSIX flags (-i, -v, -n, -c, -E, -F, -r, -l, -o, -A/-B/-C), avoid -P and GNU-only long options, and set LC_ALL=C for predictable character ranges. When you genuinely need PCRE, install GNU grep (ggrep) on macOS and branch on the OS.
Common errors in CI
"grep: invalid option -- P" on a macOS runner means BSD grep, which has no PCRE; use -E or ggrep. "grep: repetition-operator operand invalid" can appear when a GNU-style \{n\} or + is interpreted differently by BSD grep; switch to -E. Differing [a-z] results between runners are a locale issue, fixed by LC_ALL=C.