The problem is that in your second sed
call, you have enclosed the program in single quotes (' ... '
). While this is recommended practice, single quotes prevent the shell from expanding shell variables such as ${serviceLoopBack}
, so that text will remain verbatim instead of being replaced by the shell variable's content.
One possibility is to use double-quotes instead of single quotes, as in
sed -i -e "s,^[ \t]*services:[ \t]*,${serviceLoopBack}," "$destfile"
Alternatively, assemble the sed
expression in a shell variable using printf
:
printf -v prog 's,^[ \t]*services:[ \t]*,%s,' "$serviceLoopBack"
sed -i -e "$prog" "$destfile"
Note that I am using ,
as separator instead of /
, since your replacement text contains /
also and this would otherwise confuse sed
. Also, I omitted the g
option since I assume that there will be only one match per line.
You may want to look at the quoting in your shell script anyway, see e.g. this answer on the reasons.
However, if sed
is not a strict requirement, almost the entire shell script can be replaced with an awk
program instead (which is faster):
awk -v slb="services:|NL|- name: loopback-service|NL||FS||FS|url: http://127.0.0.1:12345|NL||FS||FS|routes:|NL||FS||FS|- name: loopback-test-route" \
'/^[ \t]*services:/{$0=slb;f=1}
{gsub(/\|NL\|/,"\n"); gsub(/\|FS\|/," ")} 1; END{if (!f) {print "\n\n" slb}}' "$destfile"
- This will import the "service loop back" specification in the
awk
variable slb
.
- It will then check if any line matches the
services:
pattern, and if so, replace the entire line with the string stored in slb
(which I infer is what you actually want to achieve). At the same time, set a flag f
to 1.
- Using
gsub()
, replace all occurences of |NL|
with a new-line, and all occurences of |FS|
with a space.
- The seemingly "stray"
1
instructs awk
to print the current line, including all modifications made so far.
- At the end, if
f
is still unset, append the "service loop back" line with the leading pattern (however, already converted to \n\n
).
Note that awk
will not edit the file in-place, unless you have an awk
implementation that understands the -i inplace
option. You may have to redirect the output to a temporary file and then replace the $destfile
with the temporary file afterwards.
All in all, however, since you are using a structured language (YAML), it might be worthwile using a dedicated parser such as yq
instead of line-oriented text processing tools.
grep -E
,[ \t]
will match the space, the backslash and the lettert
, which probably isn't what you want. Standard regexes don't support C-style backslash-escapes. (grep -P
would support them, though, along with the Perl ones.) Use[[:blank:]]
(space and tab) or[[:space:]]
(other whitespace characters too) or$'[ \t]'
(letting the shell turn the\t
into the literal TAB) instead. – ilkkachu May 17 '22 at 11:23\t
is not supported.[[:blank:]]
suit for my case. – hk6279 May 17 '22 at 14:23