2

I've spent hours searching and can't find a solution to this. I have a directory with over 1,000 PHP files. I need to replace some code in these files as follows:

Find:

session_register("CurWebsiteID");

Replace with (saved in replacement.txt:

if(!function_exists ("session_register") && isset($_SERVER["DOCUMENT_ROOT"])){require_once($_SERVER["DOCUMENT_ROOT"]."/libraries/phpruntime/php_legacy_session_functions.php");} session_register("CurWebsiteID");

Using the command below, I'm able to replace the pattern with $(cat replacement.txt) whereas I'm looking to replace them with the content of the text file.

Command being used:

find . -name "*.xml" | xargs -n 1 sed -i -e 's/mercy/$(cat replacement.txt)/g'

I've also tried using variables instead replacement=code_above; and running an adjusted version with $(echo $replacement) but that doesn't help either.

What is the correct way to achieve this?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Ralph
  • 418
  • 8
  • 18

2 Answers2

5

You don't need command substitution here. You can use the sed r command to insert file content and d to delete the line matching the pattern:

find . -name "*.xml" | xargs -n 1 sed -i -e '/mercy/r replacement.txt' -e '//d'
SLePort
  • 15,211
  • 3
  • 34
  • 44
  • 1
    OMG! That worked beautifully. Thank you very much @SlePort for the elegant solution. Cheers! – Ralph Mar 02 '17 at 19:50
2

$(...) is not interpreted inside single quotes. Use double quotes:

find . -name "*.xml" | xargs -n 1 sed -i -e "s/mercy/$(cat replacement.txt)/g"

You can also do away with cat:

find . -name "*.xml" | xargs -n 1 sed -i -e "s/mercy/$(< replacement.txt)/g"

In case replacement.txt has a / in it, use a different delimiter in sed expression, for example @:

find . -name "*.xml" | xargs -n 1 sed -i -e "s@mercy@$(< replacement.txt)@g"

See also:

Community
  • 1
  • 1
codeforester
  • 39,467
  • 16
  • 112
  • 140
  • I ran: `find . -name "*.xml" | xargs -n 1 sed -i -e "s/mercy/$(< replacement.txt)/g"` and got this error: ***sed: -e expression #1, char 128: unknown option to `s'*** – Ralph Mar 02 '17 at 19:18
  • because your replacement text has `/` chars in it. Try `s@mercy@$(<...)@g` Good luck. – shellter Mar 02 '17 at 19:23
  • @shellter I don't understand what I'm supposed to do wth `s@mercy@$(<...)@g`. The pattern I'm after doesn't have `@` in it. What does `@` do? – Ralph Mar 02 '17 at 19:25
  • 1
    Did you try it? Else here's a great `sed` tutorial : http://grymoire.com/Unix/Sed.html . Oh, and depending on your OS, you might need `\s@mercy@...` instead. Good luck. – shellter Mar 02 '17 at 19:29
  • And "actually" using `"..."` may cause you other problems, as I see values like `$_SERVER` in your replacement text will be evaluated locally as environment variables. Good luck. – shellter Mar 02 '17 at 19:31
  • @codeforester - Your last update showed some improvement. I ran `find . -name "*.xml" | xargs -n 1 sed -i -e "s@mercy@$(< replacement.txt)@g"` and it replaced it with the content of the file, however it replaced `&&` within the file with `mercymercy`, odd. Thanks a lot for the assistance. – Ralph Mar 02 '17 at 19:47
  • `&` stands for the string that was matched by the pattern after `s/`, which was `mercy`. So, `&&` would become `mercymercy`. As @shellter pointed out, special characters like `$` and `&` in replacement.txt can cause problems for your `sed`. – codeforester Mar 02 '17 at 19:50