Skip to content
Latchkey

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

Terminal
# 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.txt

Options

DifferenceGNU vs BSD
-P (PCRE)GNU only; BSD grep has no -P
--include / --exclude-dirGNU; modern BSD grep supports them, older did not
--colorBoth, but default aliasing differs
-z behaviorBoth support it; binary handling differs slightly
--no-group-separatorGNU 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.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →