Reputation: 3956
I have looked through many posts here and elsewhere on this subject, but none of the solutions offered seem to work for me. I need to replace a string (which contains buggy nonsensical PHP code) with another string (containing the correct PHP code) in all files within a particular folder. I understand that the only characters that need escaping when using sed are ampersands, backslashes, and whichever character is used as the delimiter.
The string I want to search for is:
$arguments = func_get_args();$numargs = func_num_args();for($i=1; $i < $numargs; $i++){$arguments[$i] = $arguments = func_get_args();$arguments[$i];}
The string I want to replace it with is:
$arguments = func_get_args();$numargs = func_num_args();for($i=1; $i < $numargs; $i++){$arguments[$i] = &$arguments[$i];}
I have tried numerous variations but cannot get it to work. I think the following command should work (but doesn't).
find /folder/to/search -name Function.php -type f -exec sed -i 's|$arguments = func_get_args();$numargs = func_num_args();for($i=1; $i < $numargs; $i++){$arguments[$i] = $arguments = func_get_args();$arguments[$i];}|$arguments = func_get_args();$numargs = func_num_args();for($i=1; $i < $numargs; $i++){$arguments[$i] = \&$arguments[$i];}|' {} \;
This is driving me insane - any assitance would be greatly appreciated!
Upvotes: 0
Views: 26562
Reputation: 189327
I understand that the only characters that need escaping when using sed are ampersands, backslashes, and whichever character is used as the delimiter
Not true for the search expression. It is a regular expression; for literal matching, you need to escape all regex specials, i.e. at least s%\([][^$.\*]\)%\\\1%g
(off the cuff - I might have missed a few, and/or your sed may differ from mine). Luckily, this is easy to do programmatically, e.g. with sed - just be careful so you don't get confused.
The replacement string is a literal string, except for backreferences, so for that part your statement is true.
#!/bin/sh
from=`sed 's%[][^$.\*]%\\\&%'<<'____HERE'
$arguments = func_get_args();$numargs = func_num_args();for($i=1; $i < $numargs; $i++){$arguments[$i] = $arguments = func_get_args();$arguments[$i];}
____HERE`
to=`cat<<'____THERE'
$arguments = func_get_args();$numargs = func_num_args();for($i=1; $i < $numargs; $i++){$arguments[$i] = \&$arguments[$i];}
____THERE`
find /folder/to/search -name Function.php -type f -exec sed -i "s|$from|$to|" {} \;
Upvotes: 2
Reputation: 3956
I finally found the right syntax. Contrary to all the advice I have read, I needed to escape the dollar signs and open square brackets in BOTH expressions (but not the close square brackets nor the curved brackets). So here is the command that finally worked ok for me:
find /folder/to/search -name Function.php -type f -exec sed -i 's/\$arguments\[\$i] = \$arguments = func_get_args();\$arguments\[\$i];/\$arguments\[\$i] = \&\$arguments\[\$i];/' {} \;
Thanks again to those who replied.
Upvotes: 4