0

My current script looks like this:

replacement="Hello"

sed -i 's/\(^TEXT_BLOCK=\).*/\1replacement/' path

I want to be able to replace the variable TEXT_BLOCK located in my config file with the contents of the variable replacement. I have tried \1$replacement and \1#replacement# but they do not give me my desired outcome.

Hardcoding it like this works for me but I do not want to hardcode. I want to be able to assign TEXT_BLOCK to a variable's value:

sed -i 's/\(^TEXT_BLOCK=\).*/\1Hello/' path
2
  • 3
    You need something like sed -i "s/^\\(TEXT_BLOCK=\\).*/\\1$replacement/" path, double quotes and $var. Commented Jul 23, 2021 at 16:05
  • @WiktorStribiżew unfortunately, this won't work for any value of $replacement; try e.g. with replacement="/"; so I'd suggest using a Perl one-liner or so, instead of sed here. Commented Jul 23, 2021 at 18:03

2 Answers 2

1

For a simple replacement sed -i "s/^\\(TEXT_BLOCK=\\).*/\\1$replacement/" path will work.
When replacement has a special character, you would like to use a different delimiter in the sed command.

replacement="with a /"
delim=$'\001'; sed 's'${delim}'\(^TEXT_BLOCK=\).*'${delim}'\1'"$replacement"${delim} path

However, this will still fail when the replacement has a &. This character will also cause problems in the "solution"

replacement="Hello"
t='TEXT_BLOCK'
awk -v r="${replacement}" -v key=${t} '{sub("^" key "=.*",key "=" r );print}'

When you want to catch such a replacement value too, you can use

replacement="Hello /& <- strangers"
t='TEXT_BLOCK'
awk -v r="${replacement//&/\\\\&}" -v key=${t} '{sub("^" key "=.*",key "=" r );print}'
Sign up to request clarification or add additional context in comments.

Comments

0

Note that the sed one-liner suggested in the comments (sed -i "s/^\\(TEXT_BLOCK=\\).*/\\1$replacement/" path) won't work for some values of $replacement.

E.g., if the variable contains a /, you'd get:

replacement="Hello/"
echo 'TEXT_BLOCK=init' | sed -e "s/^\\(TEXT_BLOCK=\\).*/\\1$replacement/"
# → sed: -e expression #1, char 30: unknown option to `s'

Albeit the OP's question is tagged with sed, I'd suggest to write some perl -wpe one-liner instead, to have a more robust script, and given perl is a fairly standard dependency, it should probably be available on the OP's target machine.

To write one such script, you could just rely on the Perl operators s/// and BEGIN{ }.

Proof of concept:

#!/usr/bin/env bash
subst() {
  re="$1"
  str="$2"
  perl -wpe 'BEGIN {$re=shift @ARGV; $str=shift @ARGV;}; s/$re/$str/g;' "$re" "$str"
}

# Usage example
echo $'TEXT_BLOCK="init"\nEnd.' | subst '^TEXT_BLOCK=.*$' 'TEXT_BLOCK="3$/"'

# will print:
#   TEXT_BLOCK="3$/"
#   End.

Note that this can easily be adapted to the sed -i use case:

#!/usr/bin/env bash
subst_i() {
  fil="$1"
  re="$2"
  str="$3"
  perl -i -wpe 'BEGIN {$re=shift @ARGV; $str=shift @ARGV;}; s/$re/$str/g;' "$re" "$str" "$fil"
}

# Usage example
echo $'TEXT_BLOCK="init"\nEnd.' > data.txt
subst_i data.txt '^TEXT_BLOCK=.*$' 'TEXT_BLOCK="3$/"'
cat data.txt

1 Comment

BTW, regarding the issue mentioned in the recent awk answer, note that this perl answer is also robust w.r.t. strings containing the & character.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.