tags:

views:

185

answers:

3

I have been through the sed one liners but am still having trouble with my goal. I want to substitue matching strings on all but the first occurrence of a line. My exact usage would be:

 $ echo 'cd /Users/joeuser/bump bonding/initial trials' | sed <<MAGIC HAPPENS>
 cd /Users/joeuser/bump\ bonding/initial\ trials

The line replaced the space in bump bonding with the slash space bump\ bonding so that I can execute this line (since when the spaces aren't escaped I wouldn't be able to cd to it).

Update: I solved this by just using single quotes and outputting

 cd 'blah blah/thing/another space/'

and then using source to execute the command. But it didn't answer my question. I'm still curious though... how would you use sed to fix it?

A: 
s/ /\\ /2g

The 2 specifies that the second one should apply, and the g specifies that all the rest should apply too. (This probably only works on GNU sed. According to the Open Group Base Specification, "If both g and n are specified, the results are unspecified.")

Chris Jester-Young
You are correct about the GNU sed. On my Mac it doesn't work. But this is the exact kind of elegant solution I was looking for.
vgm64
+1  A: 

use awk

$ echo cd 'blah blah/thing/another space/' | awk '{for(i=2;i<NF;i++) $i=$i"\\"}1'
cd blah\ blah/thing/another\ space/

$ echo 'cd /Users/joeuser/bump bonding/initial trials' | awk '{for(i=2;i<NF;i++) $i=$i"\\"}1'
cd /Users/joeuser/bump\ bonding/initial\ trials
ghostdog74
+2  A: 

You can avoid the problem with g and n

Replace all of them, then undo the first one:

sed -e 's/ /\\ /g' -e 's/\\ / /1'

Here's another method which uses the t branch-if-substituted command:

sed ':a;s/\([^ ]* .*[^\\]\) \(.*\)/\1\\ \2/;ta'

which has the advantage of leaving existing backslash-space sequences in the input intact.

Dennis Williamson
Your first answer looks to be the universal solution. With a little reading, the -e flag seems to be what I was really looking for.
vgm64