Here is a single invocation of sed that writes the revised line to stdout while at the same time saving the removed text in shell variable
$ var=$(echo "This X is test Y. But X is not test Y." | sed -nr 'h;s/[^X]*X([^Y]*)Y.*/\1/;p;x;s/X[^Y]*Y/REPLACE/;w /dev/stderr') 2>&1
This REPLACE. But X is not test Y.
The value of
$ echo "==$var=="
== is test ==
This command copies the current pattern to the hold space.
This removes everything from the pattern space except the text between the first
Y including any spaces. This is then printed to stdout. This is the output that is captured by the shell and assigned to
This copies the hold space back to the pattern space. When this is done, the pattern space contains a copy of the original input line.
s/X[^Y]*Y/REPLACE/; w /dev/stderr
The substitution is made and the result is written to
After the shell has captured stdout into
var, this instructs the shell to copy stderr (which has the line with REPLACE) to stdout.
Aside on handling of variable
var includes the leading and trailing spaces. If the shell were to subsequently subject
var to word-splitting, these spaces would be removed. To prevent that, when
var is referenced, do so inside double-quotes, as in the example above.