2

I have a configuration script which does basically this:

#!/bin/bash

source vars.sh

cat >foo.output <<EOF
# some static stuff (many lines...)
variable_bit=($SOME_VAR, $SOME_OTHER_VAR, ...)
# some more static stuff (many lines...)
EOF

It would be nicer to have some other file, call it foo.output.template, which looked like this

# some static stuff (many lines...)
VARIABLE_BIT
# some more static stuff (many lines...)

Then, my configuration script could do something like this

sed 's/VARIABLE_BIT/<<STDIN>>/' foo.output.template >foo.output <<EOF
variable_bit=($SOME_VAR, $SOME_OTHER_VAR, ...)
EOF

This won't work, and I don't know if sed can do this, but the intention is that it

  • reads foo.output.template
  • matches VARIABLE_BIT
  • replaces this with whatever is in stdin
  • then pipes to foo.output

Can sed, awk, or some other common *nix utility do this easily?

spraff
  • 911
  • 4
  • 14
  • 29

3 Answers3

4

At least if you have GNU sed, then given

$ cat foo.output.template
# some static stuff (many lines...)
VARIABLE_BIT
# some more static stuff (many lines...)

and

$ cat bar
hello
hello

then you can match VARIABLE_BIT, read and insert the contents of bar, then delete VARIABLE_BIT:

$ cat bar | sed '/^VARIABLE_BIT/{
r /dev/stdin
d
}' foo.output.template
# some static stuff (many lines...)
hello
hello
# some more static stuff (many lines...)

You can make it into a one-liner if you are careful to avoid the d being interpreted as part of the filename

cat bar | sed -e '/^VARIABLE_BIT/{r /dev/stdin' -e 'd;}' foo.output.template

Redirect to an output file in the usual way i.e. > foo.output


Note: I have used cat bar just to illustrate standard input; if you really want to use a file for the replacement text, then you can do that directly i.e.

sed -e '/^VARIABLE_BIT/{r bar' -e 'd;}' foo.output.template > foo.output
steeldriver
  • 81,074
0

Can't you split your template into two files, one before the variable part and one after it? The shell can then concatenate them like this:

( cat foo.output.template.before; cat ; cat foo.output.template.after; ) >foo.output
Renardo
  • 304
  • 1
  • 3
  • That would be the easy hack, I'm curious as to whether there's a neat all-in-one solution. – spraff Jun 19 '18 at 21:38
  • If there are no backspace (\b) characters in your input, then here you are: sed -e "s/VARIABLE_BIT/$(tr '\n' '\b' | sed 's/.$//')/" foo.output.template | tr '\b' '\n' – Renardo Jun 20 '18 at 06:42
0
cat before.input - after.input >output <<EOF
whatever $FOO $BAR
EOF
spraff
  • 911
  • 4
  • 14
  • 29