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?

4
  • Maybe (read -r line; sed "s/VARIABLE_BIT/$line/" ... ) << ... Commented Jun 19, 2018 at 20:47
  • I'm sure this must be a duplicate - you can do something like cat foo | sed -e '/VARIABLE_BIT/{r /dev/stdin' -e 'd;}' foo.output.template > foo.output Commented Jun 19, 2018 at 22:16
  • @steeldriver That looks promising, can you please unpack what you wrote?
    – spraff
    Commented Jun 20, 2018 at 8:49
  • @spraff I have outlined an answer below Commented Jun 20, 2018 at 12:40

3 Answers 3

5

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
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
2
  • That would be the easy hack, I'm curious as to whether there's a neat all-in-one solution.
    – spraff
    Commented Jun 19, 2018 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
    Commented Jun 20, 2018 at 6:42
0
cat before.input - after.input >output <<EOF
whatever $FOO $BAR
EOF

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .