Replace Pattern with another that has Special Characters

Hello Team,

Any help would be much appreciated for the below scenario:

I have a sed command below where I am trying to replace the contents of 'old_pkey' variable with 'new_pkey' variable in a Soap request file (delete_request.txt). This works fine for regular string values, but this new_pkey has '/' that is breaking my sed command (sed: -e expression #1, char 122: unknown option to `s').

What I want to achieve is to replace the

'13670163|Customer|Home|Ask||MONTGOMERY|AL|36116' 

with

'2141899|Customer|Home|N/A||N/A|NY|N/A' in the file delete_request.txt
old_pkey='13670163|Customer|Home|Ask||MONTGOMERY|AL|36116'
new_pkey='2141899|Customer|Home|N/A||N/A|NY|N/A'

sed "s/<urn:sourceKey>$old_pkey<\/urn:sourceKey>/<urn:sourceKey>$new_pkey<\/urn:sourceKey>/g" delete_request.txt

If your script is written in bash or ksh you could try the following parameter substitution:

${pnewkey//\//\\\/}

It may be more readable to use a different delimiter in the sed expression:

sed s^to_change^new/text^g

It's what I would normally suggest, but what if your new delimiter is required next time?

Andrew

Sorry, forgot to mention, it is in bash.

--- Post updated at 02:49 PM ---

This works for '/'. Thanks. What about characters like \ ] * [

sed "s^<urn:sourceKey>$old_pkey<\/urn:sourceKey>^<urn:sourceKey>$new_pkey<\/urn:sourceKey>^g" delete_request.txt

You are quite free in selecting delimiters for sed 's s command:
info sed :

so the / don't need to be escaped any more.

But, as apmcd47 already pointed out, you need to make sure that the selected delimiter doesn't show up explicitly in your regex nor replacement, nor does any character with a special meaning in regexes, like the ones you mentioned.
For single special chars, you might fall back to your shell's "Parameter Expansion / Pattern substitution" as alluded to by apmcd47, so your command would look like

sed "s^<urn:sourceKey>${old_pkey//[/\\[}</urn:sourceKey>^<urn:sourceKey>${new_pkey//[/\\[}</urn:sourceKey>^g" delete_request.txt

If you expect more than one special char, it might be easier to create a small sed command on the fly, using another sed invocation.

Hi, does it have to be sed? Try using literal strings instead of regex substitution :

awk -v old="$old_pkey" -v new="$new_pkey" '{while(i=index($0,old)) $0=substr($0, 1, i-1) new substr($0, i+length(old))}1' file

or

perl -spe 's/\Q$old/$new/g' -- -old="$old_pkey" -new="$new_pkey" file
1 Like

Wow, an example with perl -s :cool:

As RudiC said, you can use characters other than "/" as the field delimiter in sed , but there are two characters that the standards say cannot be used: a <newline> character and a <null> character are not allowed as the field delimiter.

Note that nothing says that the delimiter has to be a printable character. If you're in a single person office, using ctl-g (i.e., hold down the control key and then hit the "g" key) uses the terminal's alert character as your field delimiter. On many terminals the alert character is a bell sound (which is why I only suggest using it if you do not have an office mate).

If you do this in a script you will need to heavily comment it since if someone uses cat or lpr to look at your script, it will be unreadable. In vi it will display as ^G .

1 Like

An unusual printable delimiter :confused:

$ echo yanetut | sed ssnss
yaetut

:smiley:

1 Like

:slight_smile: Another one:

$ echo rest | sed serene
nest