Skip to content

Comments

chore: build scripts use sed -E for cross-OS compatibility#3275

Open
alex-courtis wants to merge 2 commits intomasterfrom
chore-sed-bsd-compatibility
Open

chore: build scripts use sed -E for cross-OS compatibility#3275
alex-courtis wants to merge 2 commits intomasterfrom
chore-sed-bsd-compatibility

Conversation

@alex-courtis
Copy link
Member

@alex-courtis alex-courtis commented Feb 23, 2026

Many thanks to @Uanela for finding this one: #3261 (comment)

I'd be really grateful for your testing with the "standard" macos sed.

@v3ceban
Copy link

v3ceban commented Feb 23, 2026

Oh, I had a lot of "fun" with this as well in the past! GNU and BSD (default macOS) sed are slightly different, particularly around the -i flag (GNU: sed -i, BSD: sed -i '') and how the r command behaves inside brace groups and with multiple -e expressions. The person here summarized the differences well. Below are a couple of workarounds that I found with a simple example from the help-defaults.sh:


Current usage:

sed -i -e "/${inject}/r /tmp/DEFAULT_OPTS.6.lua" -e "/${inject}/d" "${WIP}"

Workarounds:

  1. Avoid using -i flag entirely and do a two-stage pipe to first filter, then delete, then replace:
# NOTE: POSIX `r` command reads the filename until end of line,
# so a newline is required after the filename to terminate it.
# GNU sed treats the end of the -e string as a line boundary, so it works, but technically it's not POSIX compliant.
sed "/${inject}/r /tmp/DEFAULT_OPTS.6.lua
" "${WIP}" | sed "/${inject}/d" > "${WIP}.tmp" && mv "${WIP}.tmp" "${WIP}"
  1. Maintain two variants of the command and use the correct one for the given OS:
if [ "$(uname -s)" = "Darwin" ]; then
  sed -i '' "/${inject}/r /tmp/DEFAULT_OPTS.6.lua
  " "${WIP}"
  sed -i '' "/${inject}/d" "${WIP}"
else
  sed -i -e "/${inject}/r /tmp/DEFAULT_OPTS.6.lua" -e "/${inject}/d" "${WIP}"
fi
  1. Replace sed with POSIX awk, which should behave the same on both systems:
awk "/${inject}/{while((getline line < \"/tmp/DEFAULT_OPTS.6.lua\") > 0) print line; next} {print}" "${WIP}" > "${WIP}.tmp" && mv "${WIP}.tmp" "${WIP}"
  1. Require macOS users to install gsed and run the scripts with it on PATH:
PATH="$HOMEBREW_PREFIX/opt/gnu-sed/libexec/gnubin:$PATH" make help-update

or conditionally call gsed instead of sed based on user's OS (similar to the second workaround).

@Uanela
Copy link
Collaborator

Uanela commented Feb 23, 2026

@alex-courtis I will test this one shortly

@alex-courtis
Copy link
Member Author

Below are a couple of workarounds that I found with a simple example from the help-defaults.sh:

Nice one @v3ceban , many solutions there.

1 is clear and simple. Using -i is not really necessary and is fragile and confusing.

3 is pragmatic, simple, compatible and there is precedent with doc-comments.sh

2 and 4 aren't very friendly and create friction.

Let's see how it tests.

@alex-courtis alex-courtis force-pushed the chore-sed-bsd-compatibility branch from f55a655 to c534eaf Compare February 25, 2026 02:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants