Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I need to substitute some text inside a text file with a replacement. Usually I would do something like

sed -i 's/text/replacement/g' path/to/the/file

The problem is that both text and replacement are complex strings containing dashes, slashes, blackslashes, quotes and so on. If I escape all necessary characters inside text the thing becomes quickly unreadable. On the other hand I do not need the power of regular expressions: I just need to substitute the text literally.

Is there a way to do text substitution without using regular expressions with some bash command?

It would be rather trivial to write a script that does this, but I figure there should exist something already.

share|improve this question
    
Necessary to do it through bash? A simplistic solution would be to open in Word and do a find and replace all –  Akash May 9 '12 at 15:04
7  
@akash Because systems that have bash always ship with Microsoft Word? ;) No.. Just kidding. The OP might want to do this on a remote machine or for a batch of files though. –  slhck May 9 '12 at 15:07
    
@slhck :) Well, I guess gedit should have a similar option –  Akash May 9 '12 at 15:09
    
An option would be to somehow correctly escape everything before passing it to sed, which is probably a futile effort considering all the switches and platform differences. –  l0b0 May 9 '12 at 15:11

3 Answers 3

up vote 4 down vote accepted

When you don't need the power of regular expressions, don't use it. That is fine.
But, this is not really a regular expression.

sed 's|literal_pattern|replacement_string|g'

So, if / is your problem, use | and you don't need to escape the former.

ps: about the comments, also see this Stackoverflow answer on Escape a string for sed search pattern.


Update: If you are fine using Perl try it with \Q and \E like this,
perl -pe 's|\Qliteral_pattern\E|replacement_string|g'
RedGrittyBrick has also suggested a similar trick with stronger Perl syntax in a comment here

share|improve this answer
    
Thank you, I did not know about the difference between / and | –  Andrea May 9 '12 at 15:18
8  
I'm not sure this answer is useful... The only difference between s||| and s/// is that the seperator character is different and so that one character doesn't need escaping. You could equally do s###. The real issue here is that the OP doesn't want to have to worry about escaping the contents of literal_pattern (which is not literal at all and will be interpreted as a regex). –  Benj May 9 '12 at 15:31
3  
This will not avoid the interpretation of other special characters. What if search for 1234.*aaa with your solution it match much more than the intended 1234\.\*aaa. –  Matteo May 9 '12 at 15:47

You could also use perl's \Q mechanism to "quote (disable) pattern metacharacters"

perl -pe 'BEGIN {$text = q{your */text/?goes"here"}} s/\Q$text\E/replacement/g'
share|improve this answer
    
Or perl -pe 's(\Qyour */text/?goes"here")(replacement)' file –  RedGrittyBrick May 9 '12 at 22:52

I pieced together a few other answers and came up with this:

function unregex {
   # This is a function because dealing with quotes is a pain.
   # http://stackoverflow.com/a/2705678/120999
   sed -e 's/[]\/()$*.^|[]/\\&/g' <<< "$1"
}
function fsed {
   local find=$(unregex "$1")
   local replace=$(unregex "$2")
   shift 2
   # sed -i is only supported in GNU sed.
   #sed -i "s/$find/$replace/g" "$@"
   perl -p -i -e "s/$find/$replace/g" "$@"
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.