we have an sed command in our script to replace the file content with values from variables
for example..
export value="dba01upc\Fusion_test"
sed -i "s%{"sara_ftp_username"}%$value%g" /home_ldap/user1/placeholder/Sara.xml
the sed command ignores the special characters like '\' and replacing with string "dba01upcFusion_test" without '\' It works If I do the export like export value='dba01upc\Fusion_test' (with '\' surrounded with ‘’).. but unfortunately our client want to export the original text dba01upc\Fusion_test with single/double quotes and he don’t want to add any extra characters to the text. Can any one let me know how to make sed to place the text with special characters..
Before Replacement : Sara.xml
<?xml version="1.0" encoding="UTF-8"?>
<ser:service-account >
<ser:description/>
<ser:static-account>
<con:username>{sara_ftp_username}</con:username>
</ser:static-account>
</ser:service-account>
After Replacement : Sara.xml
<?xml version="1.0" encoding="UTF-8"?>
<ser:service-account>
<ser:description/>
<ser:static-account>
<con:username>dba01upcFusion_test</con:username>
</ser:static-account>
</ser:service-account>
Thanks in advance
Update with the benefit of hindsight, to present options:
sed
, see the - somewhat cumbersome, but now robust and generic - solution below.awk
solution that also properly handles both arbitrary search and replacement strings (but cannot incorporate regex features such as word-boundary assertions), see Ed Morton's answer.bash
solution and your input files are small and preserving multiple trailing newlines is not important, see Charles Duffy's answer.If you want a full-fledged third-party templating solution, consider, for instance,
j2cli
, a templating CLI forJinja2
- if you have Python andpip
, install withsudo pip install j2cli
.Simple example (note that since the replacement string is provided via a file, this may not be appropriate for sensitive data; note the double braces (
{{...}}
)):If you use
sed
, careful escaping of both the search and the replacement string is required, because:sed
doesn't support use of literal strings as replacement strings - it invariably interprets special characters/sequences in the replacement string.The following uses two generic helper functions that perform this escaping (quoting) that apply techniques explained at "Is it possible to escape regex characters reliably with sed?":
quoteRe()
andquoteSubst()
correctly handle multi-line strings.sed
reads a single line at at time by default, use ofquoteRe()
with multi-line strings only makes sense insed
commands that explicitly read multiple (or all) lines at once.quoteRe()
is always safe to use with a command substitution ($(...)
), because it always returns a single-line string (newlines in the input are encoded as'\n'
).quoteSubst()
with a string that has trailing newlines, you mustn't use$(...)
, because the latter will remove the last trailing newline and therefore break the encoding (sincequoteSubst()
\
-escapes actual newlines, the string returned would end in a dangling\
).IFS= read -d '' -r escapedValue < <(quoteSubst "$value")
to read the escaped value into a separate variable first, then use that variable in thesed
command.This can be done with bash builtins alone -- no sed, no awk, etc.
See the relevant part of BashFAQ #100 for information on using parameter expansion for string substitution.
You cannot robustly solve this problem with sed. Just use awk instead:
Ah, @mklement0 has a good point - to stop escapes from being interpreted you need to pass in the values in the arg list along with the file names and then assign the variables from that, rather than assigning values to the variables with
-v
(see the summary I wrote a LONG time ago for the comp.unix.shell FAQ at http://cfajohnson.com/shell/cus-faq-2.html#Q24 but apparently had forgotten!).The following will robustly make the desired substitution (
a\ta
->e\tf
) on every search string found on every line:The white space in
file
is tabs. You can shift ARGV[3] down and adjust ARGC if you like but it's not necessary in most cases.