views:

467

answers:

2

Hi mates,

On both, my Cygwin and my Linux box (Debian) I'm experiencing same issue:

I'm working in a shell script with some kind of formatting ids, I want to add a backslash () before a slash occurrence (/).

My sed script is working well at my terminal:

# export someid="314-12345/08"
# echo "${someid}" | sed 's/\//\\\//'

Output:

314-12345\/08

But not as well if i run command substitution:

# someidformatted=`echo "${someid}" | sed 's/\//\\\//'`
sed: -e expression #1, char 9: unknown option to `s'

What I'm missing here?

Thank you in advance.

+5  A: 

There's no obligation to use / as the separator for sed.

s/a/c/

May become

s#a#c#

So in your case:

someidformatted=`echo "${someid}" | sed 's#\/#\\\/#'`

would do the job.

I can only guess that the problem was caused by some lack of / escaping.

Grzegorz Oledzki
Thanks, your solution works. Is much clear to use # instead / in this case.
SourceRebels
+6  A: 

Here's what is going on. From the bash(1) man page, emphasis mine:

When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, ‘, or \. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.

So most likely you need more backslashes for the command substitution than a plain command. You can debug this by setting set -x:

# someidformatted=`echo "${someid}" | sed 's/\//\\\//'`
++ echo 314-12345/08
++ sed 's/\//\\//'
sed: 1: "s/\//\\//": bad flag in substitute command: '/'
+ someidformatted=
# someidformatted=$(echo "${someid}" | sed 's/\//\\\//')
++ echo 314-12345/08
++ sed 's/\//\\\//'
+ someidformatted='314-12345\/08'

So, you can see that an occurrence of \\ gets turned to \. Adding more backslashes works, but I prefer the $(command) form:

# someidformatted=$(echo "${someid}" | sed 's/\//\\\//')
Ville Laurikari
Thanks for your reply. +1 for other solution that accepted one and 'set -x'.
SourceRebels