2

I have this command:

sed -i 's/^CREATE DATABASE.*$//' world.sql

If I run that, it says:

sed: -I or -i may not be used with stdin

and creates a new file called orld.sql. The original file still exists afterwards.

So I guess, sed sees world.sql as a w orld.sql command?  How can I prevent that behaviour?

[This is on macOS.]

Timo
  • 23

3 Answers3

4

As far as I know, sed on MacOS is the FreeBSD flavor which requires a backup suffix to be supplied when using the -i option. The error message you get implies that it mis-interpreted parts of your command because you used the option without providing one.

So, try it with

sed -i".backup" 's/^CREATE DATABASE.*$//' world.sql

which will create a world.sql.backup and otherwise perform the in-place edit of world.sql.

Some sed versions may accept an empty backup suffix, as in sed -i '', which will prevent creation of a backup file, but you would need to look it up in the documentation for the specific version you are using. See

for more insight

AdminBee
  • 22,803
3

We need to dig into what your command line means to sed

sed -i 's/^CREATE DATABASE.*$//' world.sql

The syntax of macOS sed invocation is:

sed -i 'suffix' 'command(s)' filename(s)

The suffix is mandatory for the -i option.  If the suffix is null, there must be at least one space between -i and the suffix, as in -i ''.  This is is for macOS sed as is your case.

In the case of GNU sed there should be no space between -i and the suffix, like -i''.

  • So the strange looking string s/^CREATE DATABASE.*// is the suffix appended to the filename for saving the backup.

  • As you guessed, your intended filename world.sql becomes the sed command to be applied.

  • And since you didn't use the -e option so only one command was being expected. Of course, one can supply more by separating them with semicolon and quoting the argument. But this doesn't concern us here.

  • As you guessed, w happens to be a valid sed command to write the pattern space to the file whose name is whatever follows the w till the end of the command.

  • And so sed creates a file named orld.sql in preparation for filling it up during the execution phase.

  • And now nothing remains on the command line, so sed thinks the data is to come from the stdin. Hence you see that message from sed that in -i mode you can't take data from stdin.

guest_7
  • 5,728
  • 1
  • 7
  • 13
0

You can use the magic paramater -- to tell most versions of sed (as well as many other CLI tools) that you are done giving it switches (which generally start with - or --) and the remainder of the command line should be parsed as arguments. As such:

$ sed --in-place 's/^CREATE DATABASE.*$//' -- world.sql

Using the substitution command in this place where you are removing the entire line might, though, be more succinctly done with:

$ sed --in-place '/^CREATE DATABASE/d'

Your question also is tagged with MacOS. Macs use the BSD versions of some tools such as sed rather than the version usually included in Linux, and requires an actual parameter for --in-place. However, this parameter, if an empty string, behaves as it does on other POSIXes:

$ sed --in-place '' '/^CREATE DATABASE/d'
DopeGhoti
  • 76,081
  • 1
    If I use --, I get sed: illegal option -- - usage: sed script [-Ealnru] [-i extension] [file ...] sed [-Ealnu] [-i extension] [-e script] ... [-f script_file] ... [file ...]... – Timo Aug 29 '22 at 14:26