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:

  1. 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.)

  2. 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 is sed -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.)

  3. 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.

  4. If you have node.js anyway, think about writing a node.js script that does the editing instead of using fragile shell tools.