Using the output of a piped sed for the replacement value of a second sed
I am trying to get the version of a npm package, and use it to replace the value in another file. Specifically, I want to get the package.json
version and use that to replace the wordpress style.css
version.
I'm able to successfully get the version number using npm pkg get version | sed 's/"//g'
, but I've tried every variation to get it to put in the output of that into the s
of another piped sed
. (I've tried -e -r -i and all combinations therein, I've tried $1
, \1
, ${echo $1}
, etc...)
npm pkg get version | sed 's/"//g' | sed "s/1.0.0/$1/g" dist/style.css
(in the final version I would use -i in the second sed)
In the style.css file, I want to replace 1.0.0
with the output of npm pkg get version | sed 's/"//g'
You can't pipe variables to sed. It doesn't matter how you're writing the back-reference – there is literally no feature in sed that would actually produce the back-reference in the way that you're trying to do.
(sed only uses stdin to take the actual input text, and if you're specifying a file to edit (style.css), then stdin is not being used at all.)
When using $
inside a double-quoted string, however, it's not expanded by sed itself – it's expanded by your shell, well before sed runs. For back-references that's not good (one would use \$
to cause an actual $ to be passed to the command); but in your case, that's exactly the shell feature you need.
Instead of trying to connect both with a pipe (the 2nd sed will not accept anything piped into it), use two separate pipelines and the shell's variable substitutions:
-
Store the result from npm in a shell variable using
$(command)
or`command`
:version=$(npm pkg get version | sed 's/"//g')
(It would be slightly more "technically correct" to use
jq -r .
for unquoting npm's JSON output, but this is just a version string, so your sed will be good enough.) -
Include the variable as part of the sed command:
sed -i "s/1\.0\.0/$version/g" dist/style.css
Beware that this is expanded literally, e.g. if the version was
4.2beta
, then the actual command that'll be run issed -i "s/1\.0\.0/4.2beta/g"
– this is important if sed's/
separator may occur inside the variable. (In your case, it hopefully won't.) -
It's possible to merge both steps, e.g.
sed -i "s/old/$(npm get | sed)/g" file
, but that soon becomes nigh-unreadable, so don't do that. -
If you have node.js anyway, think about writing a node.js script that does the editing instead of using fragile shell tools.