Asked  7 Months ago    Answers:  5   Viewed   37 times

Is there an invocation of sed todo in-place editing without backups that works both on Linux and Mac? While the BSD sed shipped with OS X seems to need sed -i '' …, the GNU sed Linux distributions usually come with interprets the quotes as empty input file name (instead of the backup extension), and needs sed -i … instead.

Is there any command line syntax which works with both flavors, so I can use the same script on both systems?

 Answers

99

If you really want to just use sed -i the 'easy' way, the following DOES work on both GNU and BSD/Mac sed:

sed -i.bak 's/foo/bar/' filename

Note the lack of space and the dot.

Proof:

# GNU sed
% sed --version | head -1
GNU sed version 4.2.1
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

# BSD sed
% sed --version 2>&1 | head -1
sed: illegal option -- -
% echo 'foo' > file
% sed -i.bak 's/foo/bar/' ./file
% ls
file  file.bak
% cat ./file
bar

Obviously you could then just delete the .bak files.

Tuesday, June 1, 2021
 
TheFrack
answered 7 Months ago
56

If you use the -i option you need to provide an extension for your backups.

If you have:

File1.txt
File2.cfg

The command (note the lack of space between -i and '' and the -e to make it work on new versions of Mac and on GNU):

sed -i'.original' -e 's/old_link/new_link/g' *

Create 2 backup files like:

File1.txt.original
File2.cfg.original

There is no portable way to avoid making backup files because it is impossible to find a mix of sed commands that works on all cases:

  • sed -i -e ... - does not work on OS X as it creates -e backups
  • sed -i'' -e ... - does not work on OS X 10.6 but works on 10.9+
  • sed -i '' -e ... - not working on GNU

Note Given that there isn't a sed command working on all platforms, you can try to use another command to achieve the same result.

E.g., perl -i -pe's/old_link/new_link/g' *

Tuesday, June 1, 2021
 
rblarsen
answered 7 Months ago
14

OS X sed handles the -i argument differently to the Linux version.

You can generate a command that might "work" for both by adding -e in this way:

#      vv
sed -i -e 's|(.*).o:|$(OBJ_DIR)/1.o $(OBJ_DIR)/1.d $(TEST_OBJ_DIR)/1_utest.o:|' $@

OS X sed -i interprets the next thing after the -i as a file extension for a backup copy of the in-place edit. (The Linux version only does this if there is no space between the -i and the extension.) Obviously a side affect of using this is that you will get a backup file with -e as an extension, which you may not want. Please refer to other answers to this question for more details, and cleaner approaches that can be used instead.

The behaviour you see is because OS X sed consumes the s||| as the extension (!) then interprets the next argument as a command - in this case it begins with t, which sed recognizes as a branch-to-label command expecting the target label as an argument - hence the error you see.

If you create a file test you can reproduce the error:

$ sed -i 's|x|y|' test
sed: 1: "test": undefined label 'est'
Thursday, June 3, 2021
 
e_i_pi
answered 6 Months ago
36

This should work :

sed 's/-.*;/;/g' file > newFile
Saturday, August 7, 2021
 
mpen
answered 4 Months ago
77

For the Mac OS X sed, use -E instead of -r to get EREs. Additionally, the GNU extensions aren't there, so you'll need literal characters instead of the t and n metacharacters.

Or just install GNU sed, of course.

Friday, October 29, 2021
 
cody
answered 1 Month ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share