Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Alright, So i'm confused & out of ideas.

I'm trying to replace all the old IP addresses with a new one.

find -type f | grep \.php$ | xargs sed -r -i "s/(\'|\")(localhost|||\'|\")/\"\"/g"

I'm trying to find, all the PHP files, and replace any of the following (localhost,,, with

find * | grep \.php$ | xargs egrep "(\'|\")(localhost|||\'|\")"

After the first command is run, I want to make sure there's no traces of old values left, so i run the above command, but it unfortunately returns

siteeval/application/libraries/fetcher.url.class.php:    $this->host = "";

Anyone see what i'm doing wrong? or maybe can clue me into a better way of doing this?

share|improve this question
up vote 2 down vote accepted

Try this:

sed -e 's/\(127\.0\.0\.1\|10\.0\.32\.4\|localhost\|10\.0\.32\.5\)/'

You need to escape the parenthesis and the pipes. If you want to make sure they are always between quotes, try:

sed -e 's/\"\(127\.0\.0\.1\|10\.0\.32\.4\|localhost\|10\.0\.32\.5\)\"/'

Testing it a bit:

$ echo '""' | sed -e 's/\"\(127\.0\.0\.1\|10\.0\.32\.4\|localhost\|10\.0\.32\.5\)\"/'
$ echo '"localhost"' | sed -e 's/\"\(127\.0\.0\.1\|10\.0\.32\.4\|localhost\|10\.0\.32\.5\)\"/'

A suggestion for the future. Always try first with small samples (using echo like this), before moving to the complicated case.

*Edit: Escaped the dots too.

share|improve this answer
You should really escape the dots as well (use \.) since otherwise it will match any character. – Joe Aug 4 '09 at 21:08
here, parenthesis and pipes shall be escaped too – asdmin Aug 5 '09 at 8:34
Thanks. Just escaped the dots too. – sucuri Aug 5 '09 at 14:18

1) You have to escape periods, a period matches any character. So to have it match a literal period, you need to escape it by putting a back slash before it:


It will just seem to work because the meta-character period still matches a period.

2) Do you really need to match only IPs that are in quotes? If not that you don't have to worry about matching them and putting them back, that just makes it even more of a mess.

3) Any reason you can't simplify this by running the command multiple times for each IP?

4) Matching IP address with regex leads to insanity, and possibly convulsions, consider something like Perl's Net::IP::Match::Regexp :-)

5) Are you sure there are no carriage returns in that file confusing sed? try cat -vE file and look for ^M

6) Get rid of the grep and just pass -name '*.php' to find instead

share|improve this answer

I think the only problem you have is that you need to un-escape the single quotes. I like this slightly better, though:

find -type f -name '*.php' | xargs sed -r -i "s/\('|\"\)\(localhost|||\)\('|\"\)/${1}${3}/g"

In addition to un-escaping the single quotes, I am saving the matched quote character, so it can be restored around the new IP. Here's the grep:

find . -type f -name '*.php' | xargs egrep "('|\")(localhost|||'|\")"
share|improve this answer

Your Answer


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.