9

I'm trying to replace some text in a CMakelists.txt file with the value of a bash variable using sed, but I'm getting an error:

sed: 1: "'s/iPhone": invalid command code ?

sed command:

sed -i "" 's/iPhone Developer/'$PROVPROF'/g' CMakelists.txt

PROVPROF will always have something with this format:

iPhone Developer: Firstname Lastname (Numbers/Letters)
Otto45
  • 555
  • 2
  • 6
  • 20

4 Answers4

14

The reason this doesn't work is because sed on linux is different that sed on mac. In order for your commands to work as intended, I recommend installing gnu-sed through homebrew.

You can do this via: brew install gnu-sed --with-default-names

NOTE: --with-default-names flag will attempt to symlink gnu-sed with your sed, should be what you want but if not, I warned you!

then run hash -r on bash, or rehash on zsh.

If it does not work after that, you must manually symlink gnu-sed with sed via:

ln -s /usr/local/bin/gsed $(which sed)

pagep
  • 3,488
  • 1
  • 26
  • 47
mohamed chalal
  • 141
  • 1
  • 2
  • 2
    brew cannot handle (anymore) --with-default-names you can just run brew install gnu-sed – Ugur Kazdal May 17 '21 at 09:39
  • @UgurKazdal you can run `brew info gnu-sed` and it will tell you what to add to your PATH variable. You should add that to your .bashrc or .zshrc file in your home directory. – josue.0 Aug 20 '23 at 06:37
6

If you have characters in your variable which are the same as the delimiter you used to s, try using another delimiter instead:

sed -i '' "s|iPhone Developer|$PROVPROF|g" CMakelists.txt

Something more rare:

sed -i '' $'s\xFFiPhone Developer\xFF'"$PROVPROF"$'\xFFg' CMakelists.txt

Update:

Also, don't try to store your arguments on a variable. Word splitting would not always work the way you do. This is wrong:

command="sed -i '' 's|iPhone Developer|$PROVPROF|g' CMakelists.txt"
$command

Error message like sed: -e expression #1, char 1: unknown command: `'' would appear. On other seds the message may be different.

But you can use an array:

command=(sed -i '' "s|iPhone Developer|$PROVPROF|g" CMakelists.txt)
"${command[@]}"

It's still not commendable though. If you can run it directly, run it directly.

konsolebox
  • 72,135
  • 12
  • 99
  • 105
  • 2
    I think with OSX you might need the empty quotes on `-i`. [Check the linked question](http://stackoverflow.com/questions/4247068/sed-command-failing-on-mac-but-works-on-linux?lq=1). And check the comments to the question, the `/` isn't actually in the variable – skamazin Aug 04 '14 at 18:25
  • I see. I removed the comment then. – konsolebox Aug 04 '14 at 18:27
3

With mytxt.txt containing:

hi soldiers

Working cmd:

sed -i '' "s/hi/hello/" mytxt.txt

It's worked for me 100% sure for mac users

follow this link https://singhkays.com/blog/sed-error-i-expects-followed-by-text/

Output:

hello soldiers
0

With file.txt containing:

Angelina used to like iPhone Developers.
Now she's more of an Android Developer fan-girl.

and Bash script like:

#!/bin/bash
#
#
export MONKEY_1="Billy Bob";
export MONKEY_2="Brad Pitt";

sed -e "s/iPhone Developer/$MONKEY_1/g" -e "s/Android Developer/$MONKEY_2/g" file.txt

running it yields:

Angelina used to like Billy Bobs.
Now she's more of an Brad Pitt fan-girl.
Jan Nielsen
  • 10,892
  • 14
  • 65
  • 119