-p
enables the sed
mode where files are processed one record at a time where the equivalent of sed
's pattern space is the $_
variable (on which s{pattern}{replacement}flags
operates by default, like sed
's s
).
-i
for in-place editing (since copied by some sed
implementations).
-0777
changes the record separator from the default of newline (like in sed
) to some impossible byte value, so the files are processed as a whole (the slurp mode). Same as -g
in newer versions of perl
.
- then we have a
s{pattern}{replacement}gmxe
where:
x
allows adding whitespace (and comments) in the pattern to improve legibility.
m
makes it so that ^
matches at the start of every line in the subject instead of just as the start of the subject.
e
is for the replacement
to be interpreted as perl
code.
\s
is for any whitespace (well ASCII only by default) including newline, similar to [[:space:]]
in POSIX regexp, and \h
for horizontal whitespace (ISO8859-1 ones by default, that is space, tab, and non-breaking-space encoded as 0xA0, but importantly not newline; similar to POSIX' [[:blank:]]
).
++
is like +
but non-backtracking. Can help the matcher not get lost in a backtracking maze if there were unmatched {
/}
s.
- The important part in there is
(?1)
which recalls the regexp in the first (...)
capture group so allows for recursive regexps.
- The
replacement
applies another s{pattern}{replacement}gmrx
to $&
which is what was matched by the first regexp with:
r
returns the result of the substitution instead of applying it in place to $&
\K
marks the start of what's to K
eep from the match, so we don't discard what's matched to the left of it.
Some grep
and sed
implementations support \s
and/or *?
with -E
though. The latter is now specified by POSIX for extended regular expressions since the 2024 edition, but few implementations support it yet as of 2025.
No grep
implementation that I know has a slurp mode that matches the regexp against the whole file, though pcre2grep
comes close with its -M
for multiline mode, and GNU grep
with its -z
to process NUL-delimiter records (text files are not meant to contain NULs). By default, like sed
, they work on one line at a time. GNU sed
also has -z
for NUL-delimited records, or you can load the whole input into the pattern space programmatically in sed
code with a -e :1 -e '$!{N;b1' -e '}'
though beware some sed
s have a relatively low limit on the size of their pattern space.
With -I{}
, it splits on unquoted newlines, removeremoves trailing blanks, and handles some forms of quotes so would choke on file paths that contain those. It also means running one sed
invocation for each file. You're also not using the {}
place holder in the command.
It should be grep -rlZ ... | xargs -r0 sed ...
(-Z
like -r
being a non-standard GNU extension).